Поиск по сайту:

Как отлаживать программы на C в Linux с помощью gdb


На этой странице

  1. Основные сведения об отладчике GDB
  2. Пример использования GDB
  3. Заключение

Независимо от того, насколько вы опытный программист, любое разрабатываемое вами программное обеспечение не может быть полностью свободным от ошибок. Таким образом, выявление ошибок и их исправление — одна из важнейших задач в цикле разработки программного обеспечения. Хотя существует множество способов выявления ошибок (тестирование, самопроверка кода и т. д.), существует специальное программное обеспечение, называемое отладчиками, которое поможет вам понять, в чем именно заключается проблема, чтобы вы могли легко ее исправить.

Если вы программист C/C++ или разрабатываете программное обеспечение с использованием языков программирования Fortran и Modula-2, вам будет приятно узнать, что существует отличный отладчик — GDB — который позволяет легко отлаживать код на наличие ошибок и других проблем. В этой статье мы обсудим основы GDB, включая некоторые полезные функции/опции, которые он предоставляет.

Но прежде чем мы двинемся дальше, стоит упомянуть, что все инструкции и примеры, представленные в этой статье, были протестированы на Ubuntu 14.04LTS. Пример кода, используемый в руководстве, написан на языке C; используемая нами оболочка командной строки — bash (версия 4.3.11); мы использовали версию GDB 7.7.1.

Основы отладчика GDB

С точки зрения непрофессионала, GDB позволяет вам заглянуть внутрь программы во время ее выполнения, что позволяет вам определить, в чем именно заключается проблема. Хорошо обсудите использование отладчика GDB на рабочем примере в следующем разделе, но перед этим обсудите несколько основных моментов, которые помогут вам в дальнейшем.

Во-первых, чтобы успешно использовать отладчики, такие как GDB, вы должны скомпилировать свою программу таким образом, чтобы компилятор также выдавал отладочную информацию, необходимую отладчикам. Например, в случае компилятора gcc, который будет использоваться для компиляции примера программы C далее в этом руководстве, вам нужно использовать параметр командной строки -g при компиляции кода.

Чтобы узнать, что говорится на странице руководства компилятора gcc об этой опции командной строки, перейдите сюда.

Следующий шаг — убедиться, что в вашей системе установлен GDB. Если это не так, и вы работаете в системе на основе Debian, такой как Ubuntu, вы можете легко установить инструмент, используя следующую команду:

sudo apt-get install gdb

Для установки на любой другой дистрибутив перейдите сюда.

Теперь, когда вы скомпилировали свою программу таким образом, что она готова к отладке, и GDB находится в вашей системе, вы можете выполнить свою программу в режиме отладки, используя следующую команду:

gdb [prog-executable-name]

Хотя это запустит отладчик GDB, исполняемый файл вашей программы не будет запущен в этот момент. Это время, когда вы можете определить параметры, связанные с отладкой. Например, вы можете определить точку останова, которая сообщает GDB приостановить выполнение программы на определенном номере строки или функции.

Двигаясь дальше, чтобы фактически запустить вашу программу, вам нужно выполнить следующую команду gdb:

run

Здесь стоит упомянуть, что если ваша программа требует передачи ей некоторых аргументов командной строки, вы можете указать их здесь. Например:

run [arguments]

GDB предоставляет множество полезных команд, которые пригодятся при отладке. Хорошо обсудим некоторые из них в примере в следующем разделе.

Пример использования ГБД

Теперь у нас есть общее представление о GDB, а также о его использовании. Итак, давайте возьмем пример и применим знания там. Вот пример кода:

#include <stdio.h>

int main()
{
int out = 0, tot = 0, cnt = 0;
int val[] = {5, 54, 76, 91, 35, 27, 45, 15, 99, 0};

while(cnt < 10)
{
out = val[cnt];
tot = tot + 0xffffffff/out;
cnt++;
}

printf("\n Total = [%d]\n", tot);
return 0;
}

По сути, этот код делает следующее: он выбирает каждое значение, содержащееся в массиве val, присваивает его выходному целому числу, а затем вычисляет tot, суммируя предыдущее значение переменных и результат 0xffffffff/out.

Проблема здесь в том, что когда код запускается, он выдает следующую ошибку:

$ ./gdb-test 
Floating point exception (core dumped)

Таким образом, для отладки кода первым шагом будет компиляция программы с параметром -g. Вот команда:

gcc -g -Wall gdb-test.c -o gdb-test

Далее давайте запустим GDB и сообщим ему, какой исполняемый файл мы хотим отлаживать. Вот команда для этого:

gdb ./gdb-test 

Теперь ошибка, которую я получаю, является исключением с плавающей запятой, и, как многие из вас, возможно, уже знают, она вызвана n % x, когда x равно 0. Итак, имея это в виду, я поставил точку останова в строке номер 11, где происходит разделение. Это было сделано следующим образом:

(gdb) break 11

Обратите внимание, что (gdb) — это приглашение отладчика, я только что написал команду break.

Теперь я попросил GDB начать выполнение программы:

run

Итак, когда точка останова сработала в первый раз, вот что показал GDB в выводе:

Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb)

Как видно из приведенного выше вывода, отладчик показал строку, в которой была поставлена точка останова. Теперь давайте распечатаем текущее значение out. Это можно сделать следующим образом:

(gdb) print out
$1 = 5
(gdb)

Как видите, было напечатано значение 5. Итак, на данный момент все в порядке. Я попросил отладчик продолжить выполнение программы до следующей точки останова, что можно сделать с помощью команды c.

c  

Я продолжал делать эту работу, пока не увидел, что значение out равно нулю.

...
...
...
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) print out
$2 = 99
(gdb) c
Continuing.

Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) print out
$3 = 0
(gdb)

Теперь, чтобы подтвердить, что это именно проблема, я использовал команду GDBs s (или step) вместо c на этот раз. Причина в том, что я просто хотел выполнить строку 11, где выполнение программы в настоящее время приостановлено, и посмотреть, произойдет ли сбой в этот момент.

Вот что произошло:

(gdb) s

Program received signal SIGFPE, Arithmetic exception.
0x080484aa in main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;

Да, как подтверждается выделенным выводом выше, именно здесь было выдано исключение. Окончательное подтверждение пришло, когда я снова попытался запустить команду s:

(gdb) s 

Program terminated with signal SIGFPE, Arithmetic exception.
The program no longer exists.

Таким образом, вы можете отлаживать свои программы с помощью GDB.

Заключение

Здесь мы только коснулись поверхности, так как GDB предлагает множество возможностей для изучения и использования пользователями. Просмотрите справочную страницу GDB, чтобы узнать больше об этом инструменте, и попробуйте использовать его всякий раз, когда вы отлаживаете что-то в своем коде. С отладчиком связано некоторое время обучения, но оно того стоит.