Как разработчик, как использовать GDB для отслеживания ошибок в коде? Какие приемы и хитрости вы используете, чтобы облегчить себе жизнь?
Что приятно, когда это вариант. Мне сказали, что моя работа войдет в 21 век через год или два. Тем не менее, всегда полезно знать, как сделать что-то вручную, чтобы воспользоваться всеми функциями, такими как запуск собственных функций с переменными из текущей точки кода.
В общем, вы находите то, что не так, как должно быть, и работаете в обратном направлении, пока не поймете, почему.
Самый очевидный - самый полезный: установка точки останова на функции или номере строки и переход по коду строка за строкой.
Еще один полезный совет - иметь функции show для всех ваших структур / объектов, даже если они никогда не используются в вашей программе, потому что вы можете запускать эти функции из gdb:
gdb> p show_my_struct(struct)
My custom display of Foo:
...
Точки наблюдения тоже могут быть очень удобными, но они могут сильно замедлить вашу программу. Они прерывают поток при изменении значения переменной или адреса:
gdb> watch foo
Watchpoint4: foo
gdb>
Почему бы просто не «p my_struct» вместо «p show_my_struct (my_struct)»?
Поскольку вы можете декодировать поле флагов, запускать код проверки и т. д. Это не просто дамп значений структуры, вместо этого вы можете выгрузить значение, включая соответствующие объекты, на которые указывают. Например, если у obj1 есть список объектов obj2, вы можете вложить в него показ всех объектов obj2.
Некоторые подсказки:
На самом деле утверждения обычно удаляются при сборке без отладки (-g). Из ASSERT (3): «Если макрос NDEBUG был определен в момент последнего включения <assert.h>, макрос assert () не генерирует кода и, следовательно, ничего не делает».
Я не уверен, что назвал бы это «нормально». Обычно я сохраняю свои утверждения, и я также думаю, что сам факт использования макроса NDEBUG (в отличие, скажем, от отсутствия макроса «DEBUG») намекает на то, что разработчики assert согласились с тем, что утверждения обычно должны оставаться.
Используйте ddd, визуальный интерфейс для gdb. Это позволяет вам легко делать что-то с помощью нескольких щелчков мыши и визуализировать, как работает код, плюс в консоли отладчика у вас есть интерактивный gdb.
Вы также можете использовать Geany.
Одна особенно полезная функция gdb - это его способность проверять конечное состояние программы, в которой произошел сбой.
Чтобы проверить аварийный дамп (или файл ядра, как его чаще называют), запустите GDB следующим образом:
gdb <program-name> <core-file>
Например:
gdb a.out core
После запуска этой команды в основном файле gdb сообщит вам, как программа завершилась, и покажет, где в программе произошла ошибка:
Program terminated with signal 11, Segmentation fault.
#0 0x08048364 in foo () at foo.c:4
4 *x = 100;
В приведенном выше примере вы можете видеть, что программа завершилась из-за ошибки сегментации при попытке присвоить значение указателю. Набрав backtrace (или bt или where) в приглашении GDB, вы можете просмотреть полную трассировку программы:
(gdb) backtrace
#0 0x08048364 in foo () at foo.c:4
#1 0x0804837f in main () at foo.c:9
На этом этапе вы знаете, что main()
с именем foo()
и foo()
потерпели крах в строке 4 при попытке присвоить значение *x
. Часто это дает достаточно информации, чтобы вы могли исправить ошибку.
Я много занимаюсь разработкой параллельных программ, поэтому я обнаружил, что использование простой оболочки в python / ruby, которая позволяет мне прикреплять gdb ко всем процессам на всех узлах, и обратная связь со мной чрезвычайно полезно (я не нашел лучший способ, если кто-нибудь знает о нем, хотя, чтобы не перехватывать нить ...)
Я не уверен, насколько опытен OP, поэтому:
Документация GDB довольно приятная и всеобъемлющая. Первая глава - хорошее введение во все основы.
http://www.gnu.org/software/gdb/documentation/
Хотя это и не GDB, они связаны: Я лично обнаружил, что разбиение сложных строк на части помогает определить, какие утверждения ошибочны.
Кроме того, Valgrind (http://valgrind.org/) действительно хорош / полезен для решения проблемы переполнения буфера и тому подобного (мне не повезло с GDB для этого.
Базовый, но очень полезный - используйте текстовый интерфейс с опцией -tui.
Вы можете активировать режим gdb tui с помощью CTRL-X CTRL-A
Я делаю свою жизнь проще, используя IDE, которая интегрирует GDB! ;)