This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
courses:programming:debug [2019/03/19 11:10] pro100kot created |
courses:programming:debug [2024/02/07 07:23] (current) yaroslav.gosudarkin |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Отладка ====== | ====== Отладка ====== | ||
+ | |||
+ | Идея -- программы часто не работают так, как того хочет программист. Какие ошибки сложнее всего искать? | ||
+ | |||
+ | - Runtime errors, приводящие к немедленной остановке программы. SEGFAULT, Double free corruption и т.п | ||
+ | - Логические ошибки, которые приводят к неверному поведению программы | ||
+ | |||
+ | Есть несколько техник, как искать подобные ошибки. | ||
+ | |||
+ | ===== Способ 1. Отладочный вывод ===== | ||
+ | ==== Основные полезные моменты ==== | ||
+ | - Все отладочные выводы следует делать в поток stderr | ||
+ | - При отладке полезно использовать макросы, сообщающие, например, номер строки и имя функции | ||
+ | - Полезно уметь "отключать" отладочные сообщения | ||
+ | |||
+ | Простой пример отладочных выводов "на коленке" (более подробно этот вопрос рассматривается в статье [[http://www.valvers.com/programming/c/logging-with-gcc/|Logging with GCC]]): | ||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | #define DEBUG | ||
+ | |||
+ | int main(){ | ||
+ | #ifdef DEBUG | ||
+ | fprintf(stderr, "DEBUG: %s:%s:%d: %s\n", __FILE__, __func__, __LINE__, | ||
+ | "Debug message"); | ||
+ | #endif | ||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== Почитать подробнее ==== | ||
+ | * [[https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html|Полезные стандартные макросы]] | ||
+ | * [[http://www.valvers.com/programming/c/logging-with-gcc/|Статья про простое логгирование (Logging with GCC)]] | ||
+ | * [[http://www.gnu.org/software/libc/manual/html_node/index.html#toc-Syslog-1|Использование syslog]] | ||
+ | |||
+ | ===== Способ 2. gdb + cli ===== | ||
+ | |||
+ | GDB имеет достаточно простой, но мощный командный интерфейс и хорошую справку по нему. Пример: | ||
+ | |||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | #include <stdarg.h> | ||
+ | |||
+ | void get_int(int* val) { | ||
+ | val = NULL; | ||
+ | printf("%d\n", *val); | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | printf("Hello!"); | ||
+ | |||
+ | int* a; | ||
+ | get_int(a); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | При запуске данной программы появляется ошибка segmentation fault, т.е попытка доступа к несуществующей/чужой памяти. Что можно сделать что её найти: | ||
+ | |||
+ | - Найти строчку, где происходит непосредственно обращение к невалидной памяти | ||
+ | - Изучить состояние переменных, памяти в тот момент, когда произошла ошибка | ||
+ | |||
+ | Для этого необходимо: | ||
+ | |||
+ | - Собрать программу с добавлением отладочных данных: <code bash>gcc -g myprog.c</code> | ||
+ | - Открыть её в отладчике: <code bash>gdb ./a.out</code> | ||
+ | - Запустить программу командой run: <code bash>(gdb) run</code> | ||
+ | - Ввести исходные данные, если ваша программа получает какие-то данные на вход. Если требуется перенаправить на вход вашей программе содержимое файла, запустите ее с помощью <code bash>(gdb) run < input_file.txt</code> | ||
+ | |||
+ | Вывод для программы после команды run будет следующий: | ||
+ | |||
+ | <code bash> | ||
+ | (gdb) run | ||
+ | Starting program: /a.out | ||
+ | Program received signal SIGSEGV, Segmentation fault. | ||
+ | 0x0000555555555165 in get_int (val=0x0) at main.c:6 | ||
+ | 6 printf("%d\n", *val); | ||
+ | </code> | ||
+ | |||
+ | Теперь вы можете изучить состояние программы, например: | ||
+ | |||
+ | Написать <code bash>(gdb) where</code> и получить подробный стектрейс, чтобы узнать в каком файле и функции произошла ошибка: | ||
+ | |||
+ | <code bash> | ||
+ | (gdb) where | ||
+ | #0 0x0000555555555165 in get_int (val=0x0) at main.c:6 | ||
+ | #1 0x00005555555551ac in main () at main.c:13 | ||
+ | </code> | ||
+ | |||
+ | Изучить состояние переменных с помощью команды "p <variable_name>" | ||
+ | |||
+ | <code bash> | ||
+ | (gdb) p val | ||
+ | $1 = (int *) 0x0 | ||
+ | </code> | ||
+ | |||
+ | Если вы хотите изучить состояние программы ДО того, как ошибка случится, то можете использовать команду "b" для расстановки точек останова. https://www.opennet.ru/docs/RUS/gdb/gdb_6.html | ||
+ | |||
+ | Полезные ссылки: | ||
+ | |||
+ | * [[https://www.tutorialspoint.com/gnu_debugger|Краткий туториал с примерами отладки ломающихся программ]] | ||
+ | * [[https://habr.com/post/181738|Полезное про массивы и работу с памятью]] | ||
+ | * [[https://sourceware.org/gdb/current/onlinedocs/gdb|Полная официальная документация]] | ||
+ | |||
+ | ===== Способ 3. GDB + VSCode ===== | ||
+ | |||
+ | <color #ed1c24>WIP</color> | ||
+ | |||
+ | Чтобы использовать отладчик gdb из IDE VSCode, необходимо: | ||
+ | |||
+ | Установить расширения для отладки и работы с языком С: | ||
+ | |||
+ | {{courses:programming:screenshot_from_2024-02-07_14-11-54.png}} | ||
+ | {{courses:programming:screenshot_from_2024-02-07_14-12-01.png}} | ||
+ | |||
+ | - Открыть ваш проект/файл в VSCode | ||
+ | - Расставить точки останова напротив интересующих вас строк кода (нажать слева от номер строки) | ||
+ | - Перейти в вкладку "Debug" | ||
+ | |||
+ | {{courses:programming:screenshot_from_2024-02-07_13-51-04.png}} | ||
+ | |||
+ | Нажать комбинацию клавиш ctrl+shift+P (откроется командная консоль vscode) и написать debug. Выбрать С/C++ debugging | ||
+ | |||
+ | {{courses:programming:screenshot_from_2024-02-07_14-16-57.png}} | ||
+ | |||
+ | Сохранить файл launch.json. Теперь у вас есть конфигурация для отладки этой программы. Запустите отладку, нажав F5 | ||
+ | |||
+ | {{courses:programming:screenshot_from_2024-02-07_14-18-13.png}} | ||
+ | |||
+ | Теперь в VScode вам доступен интерфейс отладки: | ||
+ | |||
+ | - Справа панель управления отладкой | ||
+ | - Слева -- состояние памяти и переменных | ||
+ | |||
+ | {{courses:programming:screenshot_from_2024-02-07_14-18-27.png}} | ||
+ | {{courses:programming:screenshot_from_2024-02-07_14-18-34.png}} | ||
+ | |||
+ | |||
+ | ====== Архив ====== | ||
+ | |||
+ | ===== gdb + другие ide ===== | ||
+ | Любая среда разработки или даже мощный текстовый редактор обычно предоставляют вам графический интерфейс для использования gdb при отладке своих программ. Обычно он достаточно наглядный и имеет хорошее описание для каждой IDE. | ||
+ | |||
+ | Вы можете самостоятельно найти описание использования отладчика в вашей любимой IDE. Для CLion можно посмотреть эти источники: | ||
+ | * [[https://blog.jetbrains.com/clion/2015/05/debug-clion/|Debugging in CLion]] | ||
+ | * [[https://www.youtube.com/watch?v=wUZyoAnPdCY|Debugging in CLion on youtube]] | ||