Linux: Полное руководство
Шрифт:
Или еще один распространенный случай: программист забывает, что нумерация элементов массива начинается с 0, и не инициализирует первый элемент массива:
Особое место в зоопарке ошибок занимают ошибки, связанные с неправильным использованием указателей. Все эти ошибки можно условно разделить на три группы, которые я сейчас кратко перечислю.
1) Неправильное использование операторов * и &. Это самая распространенная группа ошибок начинающих программистов. Вот характерный пример такой ошибки:
2) Выделение недостаточного
3) Использование неинициализированных указателей. Такие ошибки часто встречаются при работе с динамическими структурами. Например, с линейными списками: вы забыли инициализировать главный элемент (head = NULL) и пытаетесь добавить в список новый элемент.
Использование рекурсивных вызовов может повлечь за собой ошибку переполнения стека, если вы неправильно зададите условие завершения рекурсии. Как правило, рекурсивная функция вызывает саму себя с несколько измененными параметрами. Рано или поздно такая функция должна, в зависимости от переданных параметров, возвратить какое-нибудь значение, а не опять вызвать саму себя.
Для облегчения поиска ошибок были созданы специальные программы — отладчики. Одним из самых удачных отладчиков для Linux является gdb (The GNU Debugger). Этот отладчик входит в состав всех распространенных дистрибутивов (за исключением их «урезанных» версий — для рабочих станций), и для его установки достаточно установить пакет gdb.
С помощью gdb вы сможете:
♦ запустить вашу программу с определенными аргументами;
♦ запустить программу в пошаговом режиме;
♦ установить точки останова (breakpoint);
♦ установить условие останова программы;
♦ узнать, что случилось, если программа неожиданно завершилась.
22.2. Отладчик gdb
Формат вызова отладчика gdb следующий:
Ключи отладчика описаны в таблице 22.1.
Ключи командной строки gdb Таблица 22.1
Ключ | Назначение |
---|---|
– help или -h | Вывод краткого описания всех параметров |
– nx или -n | Не обрабатывать команды файла инициализации .gdbinit |
– q | Не выводить приветствие и информацию об авторских правах |
– batch | Командный режим. Отладчик возвращает 0, если были выполнены все команды, указанные в файле, заданном параметром -x (и файле .gdbinit, если его использование разрешено). Если же хотя бы одна из команд не выполнена, возвращается ненулевое значение |
– cd=каталог | Установить рабочий каталог (по умолчанию используется текущий каталог) |
– f или -fullname | Данная опция нужна, если вы планируете использовать интерфейс текстового процессора Emacs для отладки ваших программ с помощью gdb. Для более подробного описаний обратитесь к справочной системе |
– b bps (bits per second) | Установить скорость обмена информацией по последовательному интерфейсу, если вы отлаживаете вашу программу удаленно |
– tty=терминал | Установить терминал в качестве стандартного ввода и вывода для отлаживаемой программы. |
– s файл или -symbols=файл | Читает таблицу символов из указанного файла |
– write | Разрешить запись в исполняемые и core-файлы |
– e программа | Использовать указанную программу в качестве фильтра дампа |
– se=файл | Читать таблицу символов из указанного файла и использовать указанный файл в качестве исполнимого |
– core=файл или -с файл | Указать файл дампа |
– command=файл
| Выполнить указанные в файле команды (используется в командном режиме) |
– d каталог | Добавить каталог к списку поиска исходных текстов |
[prog|core|procID] | Последний параметр задает объект, который нужно отлаживать. Вы можете задать программу (prog), или дамп-файл (core), который будет создан в случае ошибки программы (Segmentation fault), или же подсоединиться к уже запущенному процессу (procID) |
– p PID | Подключиться к уже запущенному процессу (данная опция стала доступной в версии gdb 5.2) |
Чтобы использовать gdb для отладки вашей программы, нужно добавить в исполняемый файл отладочную информацию. Для этого откомпилируете вашу программу с опцией -g:
Данная опция включает отладочную информацию в родном для операционной системы формате, с которым может работать gdb.
Затем нужно вызвать gdb так:
Если после запуска вашей программы произошла ошибка и был создан дамп-файл (core), можно передать отладчику и этот файл:
Можно также подключиться к уже запущенному процессу, для этого нужно передать его PID:
Только убедитесь сначала в том, что у вас нет файла 1111, поскольку gdb сначала ищет исполняемый файл, затем core-файл, а уже затем PID.
После запуска отладчика в интерактивном режиме вы можете использовать команды, самые важные из которых перечислены в таблице 22.2. Об остальных можно узнать в справочной системе: man gdb.
Команды gdb Таблица 22.2
Команда | Назначение |
---|---|
break [файл:]функция | Установить точку останова |
run [аргументы] | Запустить программу и передать ей указанные аргументы |
bt | Обратная трассировка: отобразить стек программы |
print выражение | Вывести значение выражении, операндами могут быть переменные, объявленные в вашей программа |
С | Продолжить выполнение программы (после останова) |
Next | Выполнить следующую строку. Это так называемый шаг «над» (step over). Если следующая строка — вызов функции, то мы выполним ее за один шаг — «перешагнем» ее |
Step | Выполнить следующую строку, Это так называемый шаг «в» (step into). Если следующая строка — вызов функции, то мы будем последовательно выполнять все операторы тела функции |
help [имя] | Вывести справку о команде отладчика или вывести общую информацию о нем |
Quit | Выход |
В данной таблице приведены далеко не все команды. Если вас интересует более полная информация, обратитесь к руководству по gdb.
22.3. Пример отладки программы
Давайте напишем программу, которая обнуляет элементы массива
Вот листинг программы:
Листинг 22.1. Демонстрационная программа, содержащая ошибку
Назовем нашу программу test.c и откомпилируем ее:
Опция – g добавляет отладочную информацию для отладчика gdb, а опция – o указывает имя результирующего файла.