Как определить, где находится ошибка в коде, который вызывает ошибку сегментации ?
Может ли мой компилятор ( gcc
) показать местоположение ошибки в программе?
c++
c
debugging
segmentation-fault
Trilarion
источник
источник
Ответы:
GCC не может этого сделать, но GDB ( отладчик ) может это сделать. Скомпилируйте вашу программу, используя
-g
ключ, например:Затем используйте GDB:
Вот хороший учебник, чтобы вы начали работать с GDB.
Где происходит segfault, это, как правило, только ключ к пониманию того, где «ошибка, которая вызывает», находится в коде. Указанное местоположение не обязательно является проблемой.
источник
bt
как сокращение дляbacktrace
.Кроме того, вы можете
valgrind
попробовать: если вы устанавливаетеvalgrind
и запускаетезатем он запустит вашу программу и отобразит трассировки стека для любых ошибок segfaults, а также для любых недопустимых операций чтения или записи памяти и утечек памяти. Это действительно довольно полезно.
источник
--leak-check=full
не поможет отладить сегфо. Это полезно только для устранения утечек памяти.Вы также можете использовать дамп ядра и затем проверить его с помощью gdb. Для получения полезной информации также необходимо скомпилировать с
-g
флагом.Всякий раз, когда вы получаете сообщение:
основной файл записывается в ваш текущий каталог. И вы можете проверить это с помощью команды
Файл содержит состояние памяти при сбое программы. Дамп ядра может быть полезен при развертывании вашего программного обеспечения.
Убедитесь, что ваша система не устанавливает нулевой размер файла дампа памяти. Вы можете установить его неограниченным с помощью:
ulimit -c unlimited
Осторожнее, хотя! что основные дампы могут стать огромными.
источник
Существует ряд доступных инструментов, которые помогают отлаживать ошибки сегментации, и я хотел бы добавить свой любимый инструмент в список: Address Sanitizers (часто сокращенно ASAN) .
Современные компиляторы поставляются с удобным
-fsanitize=address
флагом, добавляющим некоторое время компиляции и время выполнения, что делает больше проверки ошибок.Согласно документации, эти проверки по умолчанию включают обнаружение ошибок сегментации. Преимущество здесь в том, что вы получаете трассировку стека, аналогичную выводу GDB, но без запуска программы внутри отладчика. Пример:
Вывод немного сложнее, чем выводит GDB, но есть и плюсы:
Нет необходимости воспроизводить проблему, чтобы получить трассировку стека. Достаточно просто включить флаг во время разработки.
ASAN ловят гораздо больше, чем просто ошибки сегментации. Многие недостижимые доступы будут обнаружены, даже если эта область памяти была доступна для процесса.
¹ Это Clang 3.1+ и GCC 4.8+ .
источник
Ответ Лукаса о дампах ядра хорош. В моем .cshrc у меня есть:
для отображения обратного следа, введя «ядро». И штамп с датой, чтобы убедиться, что я смотрю на правильный файл :(.
Добавлено : Если есть ошибка повреждения стека , то обратная трассировка, применяемая к дампу ядра, часто является мусором. В этом случае запуск программы в GDB может дать лучшие результаты в соответствии с принятым ответом (при условии, что ошибка легко воспроизводима). А также остерегайтесь нескольких процессов, сбрасывающих ядро одновременно; некоторые ОС добавляют PID к имени основного файла.
источник
ulimit -c unlimited
сначала включить дамп ядра.Все вышеперечисленные ответы верны и рекомендуются; этот ответ предназначен только в качестве крайней меры, если ни один из вышеупомянутых подходов не может быть использован.
Если все остальное терпит неудачу, вы всегда можете перекомпилировать вашу программу с различными временными операторами отладочной печати (например
fprintf(stderr, "CHECKPOINT REACHED @ %s:%i\n", __FILE__, __LINE__);
), разбросанными по всему, что вы считаете соответствующими частями вашего кода. Затем запустите программу и посмотрите, какой последний отладочный отпечаток был напечатан непосредственно перед тем, как произошел сбой - вы знаете, что ваша программа зашла так далеко, поэтому сбой должен был произойти после этого момента. Добавьте или удалите отладочные отпечатки, перекомпилируйте и снова запустите тест, пока вы не сузите его до одной строки кода. В этот момент вы можете исправить ошибку и удалить все временные отладочные отпечатки.Это довольно утомительно, но имеет преимущество в том, что работает практически везде - единственное, чего не может быть, - это если у вас по какой-то причине нет доступа к stdout или stderr, или если ошибка, которую вы пытаетесь исправить, является гонкой. условие, поведение которого изменяется при изменении времени программы (поскольку отладочные отпечатки замедляют работу программы и изменяют ее время)
источник