- Как пользоваться gdb
- Как пользоваться gdb
- 1. Установка gdb
- 2. Компиляция программы
- 3. Запуск отладчика
- 4. Запуск программы
- 5. Точки останова
- 6. Вывод информации
- 7. Изменение информации
- 8. Вывод типа
- 9. Просмотр адресов
- 10. Просмотр памяти
- 11. Справка по программе
- Выводы
- How to Use GDB to Debug Programs in Ubuntu 20.04
- Prerequisites
- Installing Packages
- C-Program example for debugging
- Code
- Compile C Program using GCC
- Execute the test program
- Debugging an Application on Linux
- Initiate Debugger
- Debug Breakpoints
- Add Breakpoints
- Step through Breakpoints
- Information About Breakpoints
- Delete Breakpoints
- Watch Variables
- Quit Debugger
- Conclusion
- Search
- About This Site
- Latest Tutorials
Как пользоваться gdb
Программа gdb — это популярный отладчик для программ, написанных на языке программирования Си и С++. Отладчик позволяет выполнить программу пошагово, посмотреть значения всех переменных на каждом из этапов выполнения, а если это необходимо, то и дизассемблировать код и посмотреть состояние регистров процессора.
В сегодняшней статье мы рассмотрим как пользоваться gdb для отладки и анализа выполнения программ, написанных на Си. Попытаемся разобраться с основными возможностями программы.
Как пользоваться gdb
1. Установка gdb
Обычно, отладчик устанавливается вместе с другими инструментами для сборки программного обеспечения. Для установки всего необходимого в Ubuntu или Debian достаточно выполнить:
sudo apt install build-essential
Для того чтобы установить отладчик отдельно, выполните:
В CentOS или Fedora команда установки будет выглядеть следующим образом:
А для Arch Linux надо выполнить:
Теперь отладчик gdb установлен и вы можете его использовать.
2. Компиляция программы
Для того чтобы получить максимум полезной информации во время отладки, например, имена переменных и номера строк кода программу следует скомпилировать особым образом. Для примеров из этой статьи мы будем использовать такую небольшую программу на Си, в процессе будем её изменять, но начнём с этого:
#include
int main() int var1 = 0;
int var2 = 2;
char greeting[] = «Hello from losst\n»;
printf(«%s», greeting);
>
Для того чтобы всё необходимое было включено в исполняемый файл, программу надо собрать с опцией -g. В данном случае команда будет выглядеть вот так:
Затем вы можете её выполнить:
3. Запуск отладчика
Для того чтобы запустить программу достаточно передать путь к ней отладчику. Какие-либо опции указывать не обязательно:
После запуска отладчика вы попадаете в его командный интерфейс. Программа ещё не запущена, запущен только отладчик, в котором вы можете ею управлять с помощью специальных команд. Вот основные команды gdb:
- break или b — создание точки останова;
- info или i — вывести информацию, доступные значения: break, registers, frame, locals, args;
- run или r — запустить программу;
- continue или c — продолжить выполнение программы после точки останова;
- step или s — выполнить следующую строчку программы с заходом в функцию;
- next или n — выполнить следующую строчку без захода в функцию;
- print или p — вывести значение переменной;
- backtrace или bt — вывести стек вызовов;
- x — просмотр содержимого памяти по адресу;
- ptype — просмотр типа переменной;
- h или help — просмотр справки по команде;
- q или quit — выход из программы.
4. Запуск программы
Для того чтобы запустить программу надо воспользоваться командой run в консоли gdb. Просто выполните:
И программа будет запущена и выполнена. Если вам надо передать программе какие-либо аргументы, то следует их передать команде run, например:
Если программа завершилась с ошибкой, вы можете вывести стек вызовов функций для того чтобы узнать в какой именно функции возникла ошибка:
Программа сообщает на какой строчке исходного кода возникла проблема. Чтобы посмотреть весь исходник выполните команду list:
Для того чтобы вызвать ошибку Segmentation Fault и проверить как это работает можете добавить в программу такие строки и перекомпилировать её:
char *buffer = malloc(sizeof(char) * 10);
while(1) *(++buffer) = ‘c’;
>
Тут мы выделяем из памяти массив символов размером 10 элементов и заполняем его и память, которая находится за ним символами «с», пока программа не упадёт.
5. Точки останова
Неотъемлемая часть отладки приложения — это точки останова. С помощью них можно остановить выполнение программы на любом месте исходного кода или функции, а затем проанализировать все переменные, а также что происходит с программой. Сначала смотрим исходник программы:
По умолчанию команда выводит первые десять строк. Ей можно передать в качестве аргумента номер строки, строки возле которой надо отобразить или имя функции, например:
Например, давайте установим точку останова на восьмой строчке исходника:
Теперь, когда вы запустите программу на выполнение она остановиться в указанной точке:
Для того чтобы выполнить следующую строчку без входа в функцию используйте команду next:
Тогда выполнится следующая строка кода в программе. Если надо войти в функцию и посмотреть что в ней происходит следует использовать команду step:
Для отладки циклов можно устанавливать точки останова на основе условия, например, на 11-той строке, если значение переменной var1 будет 20:
Чтобы этот пример заработал добавьте в код цикла следующую строчку, как на снимке:
Посмотреть все установленные точки останова можно такой командой:
6. Вывод информации
Сами по себе точки останова не очень полезны, но после каждой остановки программы можно посмотреть полностью её состояние и значения всех переменных, а это уже намного интереснее. Для просмотра информации используется команда info, а для вывода значения конкретной переменной — print. Для того чтобы посмотреть значения всех локальных переменных выполните:
А для вывода значений аргументов функции:
Вывести значение определённой переменной можно с помощью print:
Интересно, что с помощью print можно выполнять арифметические операции и их результат не только выводится на экран, но и присваивается внутренней переменной, таким образом его можно будет вывести ещё раз позже или использовать в других вычислениях. Например:
Имя временной переменной, куда были записаны данные отображается перед самим результатом, например, в последней команде это $2. Теперь можно ещё раз вывести это значение:
Таким образом вы можете анализировать состояние программы, на каждой точке останова и искать ошибки.
7. Изменение информации
С помощью команды set можно изменить значение переменной прямо во время выполнения программы. Например:
(gdb) break 7
(gdb) run
(gdb) set var2 = 20
(gdb) print var2
8. Вывод типа
С помощью команды ptype вы можете вывести тип переменной. Например:
(gdb) break 7
(gdb) run
(gdb) ptype var2
9. Просмотр адресов
Ещё интереснее исследовать как программы на Си работают с памятью. Команда print может выводить не только выводить значения переменных, но и их адреса в памяти. Приведите программу к такому виду и перекомпилируйте её:
#include
#include
#include
int main(int argc, char *argv[]) int var1 = 0;
int var2 = 2;
char *buffer = malloc(sizeof(char) * 10);
while(var1 < 10)var1++;
*(++buffer) = ‘c’;
>
printf(«%s\n», buffer);
>
Запустите отладчик и установите точку останова на девятой строке и запустите программу:
Теперь вы можете вывести адреса всех переменных в памяти с помощью символа &. Например:
(gdb) print &argc
(gdb) print &var1
(gdb) print &buffer
(gdb) print buffer
Как видите, аргументы функции находятся в одном месте, локальные переменные в другому, но не очень далеко, а во память выделенная из кучи, на которую указывает указатель buffer — совсем далеко. Можете поменять программу и поэкспериментировать с разным количеством переменных.
10. Просмотр памяти
С помощью команды x или eXamine можно посмотреть содержимое памяти, по определённому адресу. Например, смотрим содержимое переменной var2:
Если вы не знаете адрес переменной, можно передать её имя с оператором &, он извлечет её адрес. Программа выводит шеснадцатиричное значение, и оно обычно мало о чём нам может сообщить. Для того чтобы улучшить ситуацию можно воспользоваться опциями форматирования. Можно указать тип выводимых данных с помощью таких модификаторов:
Также можно указать размер выводимого блока:
Мы пытались вывести переменную типа int. Она занимает обычно четыре байта. Для её корректного вывода используйте такие параметры:
Ещё можно указать количество блоков, которые надо выводить, например два:
Но поскольку там уже не наша переменная, эти данные не имеют смысла. Аналогично всё работает с строками, символами и другими значениями. Только обратите внимание, что если вы будете выводить переменную не одним блоком, то на результат повлияет порядок расположения байт. Значение будет выводиться задом на перед.
11. Справка по программе
Мы рассмотрели основные возможности отладчика gdb. Но если этого вам не достаточно, вы можете посмотреть справку по любой команде программы в самой программе. Для этого используйте команду help. Например, для команды exemine:
Выводы
Теперь вы знаете как пользоваться gdb для отладки своих программ. Обычно, для отладки намного удобнее использовать графический интерфейс среды программирования, но консоль дает больше возможностей и больше гибкости.
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.
How to Use GDB to Debug Programs in Ubuntu 20.04
GNU Debugger (GDB) is an open-source debugger for GNU Systems. The debugger is portable and can be used for multiple languages as C/C++ and Fortran. It can be used for debugging programs by observing their states on specific breakpoints and even altering the flow or values for further execution. Usually, the GDB runs in command-line but several GUI has been developed for it as well.
In this article, we explore how to debug C programs using GDB in Ubuntu 20.04 LTS (Focal Fossa).
Prerequisites
Note: The commands discussed in this article have been tested on Ubuntu 20.04 LTS (Focal Fossa).
Installing Packages
Install prerequisite GN packages for compiling and debugging. Run the following command in the terminal:
$ sudo apt install gcc gdb -y
C-Program example for debugging
Code
Before running, a program needs to be compiled. We are going to compile the following C code in the file main.c.
#include int main() < for (int i=0; ireturn 0; >
Compile C Program using GCC
Usually, a C code is compiled in GCC using the following command:
Another argument needs to be provided to include symbols in the binary. These symbols are used by GDB to track and debug the program. Run the following command in terminal to compile the C code:
An executable file named bin will appear.
Execute the test program
The binary file named bin can be executed like any other executable file on a command-line interface. Use the following command to run it in terminal:
The output of the code will appear.
Debugging an Application on Linux
Initiate Debugger
Run the GDB utility using following command in the terminal:
Press enter. The console for GDB terminal will appear. Enter the run command in this console to run the executable provided to the utility as an argument.
Debug Breakpoints
Add Breakpoints
Breakpoints can be added in several ways. We will be adding a breakpoint on the printf function in our code. Run the following command in terminal to add a breakpoint:
Alternatively, a line number can be used to add a breakpoint as well.
Enter the run command and the program will stop at the breakpoint.
Step through Breakpoints
Use the command continue to continue the execution of the program.
There are two other commands for different purposes of continuing the execution of the program:
- Step: steps through the next machine instruction.
- Next: steps to through the next line of code.
Abbreviations of commands can also be used. Like abbreviation of continue command is c.
Information About Breakpoints
Information about breakpoints can be observed using info command of gdb. Run the following command the terminal:
The information about breakpoints will appear.
Note: The number on the left of the breakpoint is used to refer to it by other commands.
Delete Breakpoints
A breakpoint can be deleted using the delete command and by referring to the breakpoint number observed in the output of the info utility.
Now the breakpoint has been deleted and if run, the program will execute straight to the end.
Watch Variables
Variables can be watched using the watch utility. First, we need to enter the scope in which the variable exists. For this purpose, add a breakpoint first using the following command:
Then run the code that hits this breakpoint.
Now we are in the loop where the variable i exists.
The watch command will be used to observe the previous and new value of the variable i in the loop.
Now the breakpoint generated by watch command will appear in the list of breakpoints as well. The list of breakpoints can be shown using the following command:
Moreover, we do not need the breakpoint inserted earlier. It can be easily removed using the following command:
Now if continued, the code will view values whenever the variable has changed the value and show both old and new values.
Further iterations of the program can be observed as well, using the same command.
Quit Debugger
Run the following command in the terminal to exit the debugger.
This close gdb utility and the default command-line prompt will appear.
Conclusion
In this article, we explored how to run and break a program in GDB. Moreover, it was also configured to break itself when the value of a variable has changed. We hope you can easily debug your programs in GDB after following this article.
Search
About This Site
Vitux.com aims to become a Linux compendium with lots of unique and up to date tutorials.