User Tools

Site Tools


Sidebar






Old

courses:programming:debug

This is an old revision of the document!


Отладка

Идея – программы часто не работают так, как того хочет программист. Какие ошибки сложнее всего искать?

  1. Runtime errors, приводящие к немедленной остановке программы. SEGFAULT, Double free corruption и т.п
  2. Логические ошибки, которые приводят к неверному поведению программы

Есть несколько техник, как искать подобные ошибки.

Способ 1. Отладочный вывод

Основные полезные моменты

  1. Все отладочные выводы следует делать в поток stderr
  2. При отладке полезно использовать макросы, сообщающие, например, номер строки и имя функции
  3. Полезно уметь “отключать” отладочные сообщения

Простой пример отладочных выводов “на коленке” (более подробно этот вопрос рассматривается в статье Logging with GCC):

#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;
}

Почитать подробнее

Способ 2. gdb + cli

GDB имеет достаточно простой, но мощный командный интерфейс и хорошую справку по нему. Пример:

#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;
}

При запуске данной программы появляется ошибка segmentation fault, т.е попытка доступа к несуществующей/чужой памяти. Что можно сделать что её найти:

  1. Найти строчку, где происходит непосредственно обращение к невалидной памяти
  2. Изучить состояние переменных, памяти в тот момент, когда произошла ошибка

Для этого необходимо:

  1. Собрать программу с добавлением отладочных данных:
    gcc -g myprog.c
  2. Открыть её в отладчике:
    gdb ./a.out
  3. Запустить программу командой run:
    (gdb) run
  4. Ввести исходные данные, если ваша программа получает какие-то данные на вход. Если требуется перенаправить на вход вашей программе содержимое файла, запустите ее с помощью
    (gdb) run < input_file.txt

Вывод для программы после команды run будет следующий:

(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);

Теперь вы можете изучить состояние программы, например:

Написать

(gdb) where

и получить подробный стектрейс, чтобы узнать в каком файле и функции произошла ошибка:

(gdb) where
#0  0x0000555555555165 in get_int (val=0x0) at main.c:6
#1  0x00005555555551ac in main () at main.c:13

Изучить состояние переменных с помощью команды “p <variable_name>”

(gdb) p val
$1 = (int *) 0x0

Полезные ссылки:

Способ 2. GDB + VS

Архив

gdb + другие ide

Любая среда разработки или даже мощный текстовый редактор обычно предоставляют вам графический интерфейс для использования gdb при отладке своих программ. Обычно он достаточно наглядный и имеет хорошее описание для каждой IDE.

Вы можете самостоятельно найти описание использования отладчика в вашей любимой IDE. Для CLion можно посмотреть эти источники:

courses/programming/debug.1707287283.txt.gz · Last modified: 2024/02/07 06:28 by yaroslav.gosudarkin