Astra linux gdb lazarus исполнимый файл отладчика

Как отлаживать программы на языке C в Linux с помощью отладчика GDB

Оригинал: How to debug C programs in Linux using gdb
Автор: Himanshu Arora
Дата публикации: 16 января 2017 г.
Перевод: А.Панин
Дата перевода: 7 марта 2017 г.

Вне зависимости от вашего опыта программирования, все разработанное вами программное обеспечение просто не может не содержать ошибок. По этой причине поиск и устранение ошибок являются одними из наиболее важных задач, выполняемых в рамках цикла разработки программного обеспечения. Хотя и существует несколько способов выявления ошибок в коде (тестирование, самостоятельный аудит кода и другие), для этой цели создан отдельный тип программного обеспечения под названием «отладчики», позволяющего вам найти проблемный фрагмент кода и максимально быстро исправить его.

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

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

Основные аспекты использования GDB

По сути, GDB позволяет вам заглянуть внутрь программы в процессе ее исполнения, способствуя тем самым идентификации и локализации проблемы. Мы обсудим методику использования отладчика GDB на основе примера в следующем разделе, но перед этим стоит рассмотреть несколько основных аспектов использования отладчика, которые окажутся полезными в будущем.

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

Вы можете получить дополнительную информацию о данном параметре компилятора на его странице руководства .

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

Инструкции по установке отладчика в других дистрибутивах приведены на данной странице .

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

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

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

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

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

Читайте также:  Активация windows 10 home 1909

Пример использования GDB

Теперь вы имеете базовое представление об отладчике GDB и принципе его использования. Поэтому предлагаю рассмотреть пример и применить полученные знания на практике. Это код примера:

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

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

Итак, для отладки кода в первую очередь следует скомпилировать код программы с использованием параметра компилятора -g . Это команда компиляции:

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

Теперь следует обратить внимание на то, что в процессе исполнения программы выводится сообщение об ошибке «floating point exception» и, как многие из вас наверняка знают, данная ошибка обычно связана с делением произвольного значения на ноль. Помня об этом, я помещаю точку останова в строку под номером 11, где осуществляется деление. Это делается следующим образом:

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

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

При достижении точки останова в первый раз GDB выводит следующую информацию:

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

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

Я продолжаю выполнять аналогичные действия до того момента, пока не вижу нулевое значение переменной out .

Теперь для подтверждения предположения о том, что имеется проблема, я использую команду GDB s (или step ) вместо c . Это делается потому, что я хочу, чтобы строка 11, на которой на данный момент остановилось исполнение программы, была исполнена, в результате чего исполнение программы может аварийно завершиться.

В результате случается следующее:

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

Вы можете отлаживать свои программы с помощью GDB аналогичным образом.

Заключение

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

Источник

Отладчик GNU GDB

Введение

Откровенно говоря, программа GNU GDB довольно многофункциональная. Пошаговая от­лад­ка — лишь одна из ее возможностей. В этой статье я попытался описать те лишь команды GDB, которые позволяют проводить удобную пошаговую отладку программ, на­пи­сан­ных на Free Pascal.

Чтобы программу можно было отлаживать, она должна быть откомпилирована с ключом -g .

Поскольку GDB ориентирован не на Pascal, а на C и C++, то использование GDB для от­лад­ки Pascal-программ иногда сопряжено с неудобствами.

Приведу список подводных камней, обнаруженных мною и разработчиками Free Pascal (пе­ре­чис­лен­ных в user’s manual).

  1. Отладочная информация в Free Pascal генерируется в верхнем регистре. Поэтому имена всех переменных, процедур, функций при использовании GDB должны указываться БОЛЬШИМИ БУКВАМИ.
  2. GDB не воспринимает тип extended (ведь в C такого типа нет). Обойти эту неприятность можно, если, например, включить в код такие строки
  3. К элементам многомерных массивов нужно обращаться в C-шной манере, а именно, команда выдаст первую строку массива A. Для просмотра требуемого элемента следует писать
  4. GDB не воспринимает множества.
  5. Есть трудности с поддержкой объектов (см. user’s manual за подробностями).
  6. Есть трудности с глобально переопределенными функциями. (за подробностями см. user’s manual).
  7. При отладке процедур, функций, расположенных в разных файлах, часто возникает несоответствие — смещение строк. Та строка, которую GDB показывает текущей, таковой не является, а текущая расположена строк эдак на двадцать выше. Это приводит к большим неудобствам при пошаговой отладке. Я для себя сделал из этого такую мораль — хоть GDB и позволяет отлаживать процедуры, описанные в разных файлах, но лучше этой возможностью не пользоваться, а на время отладки все вызываемые процедуры, работа которых вас заинтересует, помещать в одном файле.
Читайте также:  Не удается запустить windows поскольку критический драйвер

Все примеры отлаживались с использованием GNU GDB 5.0.

Запуск отладчика GDB

gdb [опции] [имя_файла | ID процесса]

После запуска видим «nice GDB logo» (если это почему-то раздражает, то опция -q поз­во­ля­ет не выводить это введение с ин­фор­ма­ци­ей об авторских правах и прочая). В следующей стро­ке приглашение
(gdb)
ждет ввода команды.

Ниже приводится краткий перечень команд GDB.

Краткую справку о любой команде можно получить, введя
(gdb) help [имя_команды, можно краткое]

Если при запуске GDB имя исполняемого файла не было указано (что следовало бы делать), то указать его можно командой file .

Команда file

Для того, чтобы пролистать содержимое исходника, используйте команду list (сокращенно l ; большая часть наиболее полезных ко­манд имеют сокращения). При этом под­ра­зу­ме­ва­ет­ся, что исходник расположен в том же каталоге, что и исполняемый файл. Как правило, так оно и есть.

Команда list (сокращенно l )

Пролистывает 10 строк вниз, начиная с текущей. Для пролистывания вверх следует набрать

Команда run (сокращенно r )

Запускает отлаживаемую программу под GDB. Если требуется, то после команды можно ука­зать список аргументов программы. Так­же допускается перенаправление потоков ввода и вы­во­да в другие файлы, например

Если никаких точек останова не определено, то программа выполняется тихо, при этом нам со­об­ща­ет­ся:

Если же отладчик встречает точку останова, он выдает ее номер, адрес и дополнительную ин­фор­ма­цию — текущую строку, имя про­це­ду­ры, и т.п.

И ожидает ввода команды.

Остановка отладки программы

Команда kill ( k ). Следует запрос

Здесь введено y (то есть «да»), и отладка программы прекращается. Командой run ее можно на­чать заново, при этом все точки ос­та­но­ва (breakpoints), точки просмотра (watchpoints) и точ­ки отлова (catchpoints) сохраняются.

Выход из отладчика

Команда quit ( q ).

Точки останова

Информацию о командах этого раздела можно получить, введя
(gdb) help breakpoints

Точки останова — такие, когда GDB приостанавливает выполнение программы. Как уже упо­ми­на­лось, имеется 3 типа точек ос­та­но­ва:

  1. Breakpoints — точка останова как таковая. Остановка происходит, когда выполнение доходит до определенной строки, адреса или процедуры/функции.
  2. Watchpoints — точка просмотра. Выполнение программы приостанавливается, если программа обратилась к определенной переменной — либо считала ее значение, либо изменила его.
  3. Catchpoints — точка отлова. Приостановка происходит при определенном событии (например, получение сигнала). Я не буду касаться точек останова этого типа.

Определение точек останова

Breakpoint

Команда break
(gdb) break [аргумент]
или, сокращенно
(gdb) b [аргумент]
определяет точку останова. В качестве аргумента может выступать

  • номер строки. Остановка произойдет при достижении строки программы с этим номером. То, что написано в самой строке, выполняться не будет. Например
  • имя процедуры (функции). Отладчик зайдет в эту процедуру и остановит выполнение программы. NB!! Имя процедуры (функции) должно быть указано БОЛЬШИМИ БУКВАМИ. Приведу пример:
  • если вызвать команду break без аргументов, то точка останова поставится на текущей строке.
  • также можно явно указывать адрес точки останова (перед адресом надо поставить знак * ). Приведу лишь пример для полноты описания:

Допускается использование нескольких точек останова на одной строке (функции, адресе).

Watchpoint

Существуют различные виды точек просмотра, и задаются они различными командами:

  • команда watch (сокращенно wa ) Выполнение программы приостанавливается всякий раз, когда значение указанной переменной изменяется.
    NB!! Имя переменной должно быть указано БОЛЬШИМИ БУКВАМИ.
  • команда rwatch (сокращенно rw ) Выполнение приостанавливается всякий раз, когда программа считывает значение указанной переменной.
    NB!! Имя переменной должно быть указано БОЛЬШИМИ БУКВАМИ.
  • команда awatch (сокращенно aw ) Выполнение приостанавливается всякий раз, когда программа обращается к указанной переменной, как для считывания, так и для записи.
    NB!! Имя переменной должно быть указано БОЛЬШИМИ БУКВАМИ.
Читайте также:  Как сменить пароль при запуске windows

Замечу от себя, что команды rwatch и awatch у меня почему-то капризничают — часто не ус­та­нав­ли­ва­ют точки просмотра на пе­ре­мен­ную. Зато команда watch работала всегда.

Управление точками останова

Информацию о всех установленных точках останова можно вывести командой info .

Команда info имеет много возможностей, но в данном случае воспользуемся лишь сле­дую­щим ее форматом:
(gdb) info breakpoints
или, кратко
(gdb) i b

Выводится подробная информация о всех точках останова (как breakpoints, так и watch­points), включающая — номер — breakpoint или watchpoint — активность — сколько раз прог­рам­ма натыкалась на эту точку — иные характеристики, значение которых мне не со­всем понятно

Если какая-то точка останова не нужна, то ее можно сделать неактивной с помощью ко­ман­ды disable :

Обратно, деактивированная точка останова активируется командой enable :

Статус точки останова — активна она или нет, легко обозреть той же командой info .

Если же точка останова не требуется вообще, то она может быть удалена насовсем.

Ввод этой команды без аргумента удалит ВСЕ точки останова.

Возобновление выполнения, пошаговая отладка

Информацию о командах этого раздела можно получить, введя

Команда continue ( c )

Продолжает выполнение остановленной программы. Выполнение будет происходить, пока сно­ва не встретится точка останова. В ка­чест­ве аргумента может использоваться целое чис­ло N. Это укажет отладчику проигнорировать (N-1) точку останова (вы­пол­не­ние остановится на N-ой).

Команда step ( s )

Аналог действия клавиши F7 (Trace into) в IDE. Происходит выполнение программы до тех пор, пока не будет достигнута сле­дую­щая строка ее кода. При указании аргумента — це­ло­го чис­ла N, отладчик выполняет команду step N раз (если не останавливает вы­пол­не­ние из-за точек останова или по иным причинам).

Команда next ( n )

Аналог действия клавиши F8 (Step over) в IDE. В отличие от step вызов процедуры счи­та­ет­ся единой инструкцией (не заходит в вы­зы­вае­мые процедуры, функции). Аргумент N ра­бо­та­ет так же, как и для step .

Команда finish ( fin )

Выполняет программу до момента выхода из текущей процедуры (функции). Если функция воз­вра­ща­ет значение, то это значение вы­во­дит­ся тоже.

Команда until ( u )

Производит выполнение программы до тех пор, пока не будет достигнута строка с номером, боль­шим текущего. Команду until удоб­но применять при отладке циклов. Остановка про­и­зой­дет также, если программа при выполнении цикла выйдет из текущей про­це­ду­ры, функ­ции.

Команда stepi ( si )

Действие подобно step , но выполняется не строка, а ровно одна инструкция в этой строке прог­рам­мы. Аргумент N нужен, если тре­бу­ет­ся выполнить N инструкций.

Команда nexti ( ni )

Аналогична stepi , но вызовы процедур трактуются как одна инструкция.

Управление состоянием (просмотр, изменение) переменных при отладке

Информацию о командах этого раздела можно получить, введя

Команда print ( p )

Вывод текущего значения переменной (выражения). При использовании команды print имя пе­ре­мен­ной можно писать в сме­шан­ном регистре, то есть в этом случае использование боль­ших букв обязательным не является.

Часто требуется отслеживать значения нескольких переменных. Чтобы не утруждать себя мно­го­крат­ным вводом команды print , ис­поль­зуй­те команду display .

Команда display

В качестве аргумента обычно указывают переменную или выражение. При этом указанная пе­ре­мен­ная (выражение) занесется в дис­плей, то есть станет выводиться при каждой ос­та­нов­ке программы (при попадании на точку останова, при пошаговом вы­пол­не­нии командами step и next , etc). Если вызвать display без аргументов, то GDB выдаст значения всех пе­ре­мен­ных (вы­ра­же­ний), занесенных в дисплей.

Управление списком этих переменных осуществляется аналогично точкам останова. А имен­но, команда info display

выдаст все переменные, занесенные в дисплей. Любая переменная в списке дисплея может быть дезактивирована

или активирована заново

Удаление переменной из списка дисплея производится командой delete или командой undisplay . Так, команда

делает то же, что и

Опять-таки, если не указать номер переменной, то очистится весь список отображаемых пе­ре­мен­ных.

Изменение значения переменной

И последнее. Изменение значения переменной на другое можно, например, произвести с по­мощью команд set или print .

При использовании set присваивание происходит «тихо». То же самое можно сделать, но с по­мощью команды print .

При этом, как видно, выводится новое значение переменной.

Источник

Оцените статью