(gdb) where
#0 __strtol_internal (nptr=0x0, endptr=0x0, base=10, group=0)
at strtol.c:287
#1 0x40096fb6 in atoi (nptr=0x0) at ../stdlib/stdlib.h:251
#2 0x804863e in main (argc=1, argv=0xbffff5e4) at main.c:8
Как нетрудно заметить, функция main()
вызвала функцию atoi()
, передав ей нулевой указатель, что и стало причиной ошибки.
С помощью команды up
можно подняться но стеку на два уровня, дойдя до функции main()
:
(gdb) up 2
#2 0x804863е in main (argc=1, argv=0xbffff5e4) at main.c:8
8 i = atoi(argv[1]);
Заметьте, что отладчик нашел исходный файл main.c
и отобразил строку, где располагается ошибочный вызов функции. Узнать значение нужной локальной переменной позволяет команда print
:
(gdb) print argv[1]
$2 = 0x0
Это подтверждает нашу догадку о том, что причина ошибки — передача функции atoi()
указателя NULL
.
Установка контрольной точки осуществляется посредством команды break
:
(gdb) break main
Breakpoint 1 at 0x804862e: file main.c, line 8.
В данном случае контрольная точка размещена в первой строке функции main()
. Давайте теперь заново запустим программу, передав ей один аргумент:
(gdb) run 7
Starting program: reciprocal 7
Breakpoint 1, main (argc=2, argv=0xbffff5e4) at main.c:8
8 i = atoi(argv[1]);
Как видите, отладчик остановился на контрольной точке- Перейти на следующую строку можно с помощью команды next
:
(gdb) next
9 printf("The reciprocal of %d is %g\n", i,
reciprocal(i));
Если требуется узнать, что происходит внутри функции reciprocal()
, воспользуйтесь командой step
:
(gdb) step
reciprocal (i=7) at reciprocal.cpp:6
6 assert(i != 0);
Иногда удобнее запускать отладчик gdb
непосредственно из редактора Emacs, а не из командной строки. Для этого следует ввести в редакторе команду M-x gdb
. Когда отладчик останавливается в контрольной точке, редактор Emacs автоматически открывает соответствующий исходный файл. Не правда ли. проще разобраться в происходящем, глядя на весь файл, а не на одну его строку?
1.5. Поиск дополнительной информации
В каждый дистрибутив Linux входит масса полезной документации. В ней можно прочесть почти все из того, о чем говорится в этой книге (хотя это, очевидно, займет больше времени). Документация не всегда хорошо организована, поэтому поиск нужной информации требует определенной изобретательности. Иногда представленные факты оказываются устаревшими, так что не стоит всему слепо верить.
Ниже описаны наиболее полезные источники информации о программировании в Linux.
1.5.1. Интерактивная документация
В дистрибутивы Linux входят man
-страницы с описанием большинства стандартных команд, системных вызовов и стандартных библиотечных функций. Интерактивная документация разбита на разделы, которым присвоены номера. Для программистов наиболее важными являются следующие разделы:
(1) пользовательские команды;
(2) системные вызовы:
(3) стандартные библиотечные функции:
(8) системные/административные команды.
Числа обозначают номера разделов. Для доступа к страницам интерактивной документации применяется команда man
. Она имеет вид man имя
, где имя — название команды или функции. Иногда одно и то же имя встречается в разных разделах. В этом случае номер раздела нужно указать явно, поставив его перед именем. К примеру, так вызывается страница с описанием команды sleep
(находящаяся в первом разделе):
% man sleep
А следующая команда вызывает страницу с описанием библиотечной функции sleep()
:
% man 3 sleep
Каждая man
-страница содержит однострочное резюме команды или функции. Команда whatis
имя отображает список всех man
-страниц (во всех разделах), связанных с указанным именем. Если не известно точно, описание какой команды или функции требуется, можно выполнить поиск по ключевому слову в строках резюме с помощью команды man -k ключевое_слово
.
Страницы интерактивной документации содержат множество полезной информации и являются первым источником, к которому следует обращаться за помощью. В случае команды man
-страница описывает ее флаги и аргументы, входные и выходные значения, коды ошибок установки по умолчанию и т.п. В случае системного вызова или библиотечной функции описываются параметры и возвращаемые значения, коды ошибок и побочные эффекты, а также указывается, какие файлы заголовков нужно включать в программу при использовании функции.