Информация об изменениях

Сообщение Re: Анализ дампа с целью поиска segfault от 09.08.2017 7:14

Изменено 09.08.2017 7:27 Кузнец

Re: Анализ дампа с целью поиска segfault
Спасибо всем отозвавшимся. Каждый ответ оказался очень полезен. Дампы сделаны, разобраны, ошибка успешно найдена.

Чтобы подвести небольшой итог, сделаю ответ, собирающий все рекомендации, на случай если кто-то будет читать тему.

Итак, ситуация — есть слёт, который не выходит поймать в отладчике, но поймать очень хочется. Система linux debian, но думаю, это подойдёт для любого линукса.

Сначала нужно получить дамп. Для этого следуем инструкции по ссылке: . Там достаточно понятно описано, как включить сброс дампов при слётах процессов. Единственное, на что нужно обратить особое внимание — у меня почему-то максимальный размер дампа после простоя системы сбрасывался на 0, так что имеет смысл периодически мониторить его значение и при необходимости выставлять обратно в unlimited: -ulimit -c, ulimit -c unlimited .

Также у нас при тесте один раз почему-то дампы перестали сбрасываться, хотя ограничение стояло unlimited, после перезагрузки компа всё нормально заработало, возможно это был глюк, пока не разбирались.

Итак, по инструкции включаем дампы, затем запускаем приложение и добиваемся слёта. При слёте в выбранном каталоге появится файл core.Name.12345, здесь Name — название бинарника, 12345 — id процесса. Этот файл и есть наш дамп. Здесь нужно обратить внимание на один момент, приложение можно скомпилировать в релизной сборке, либо в отладочной сборке, лучше в отладочной, тогда анализ дампа сможет показать прямо строку в коде, в которой произошёл слёт, если отладочная сборка не падает, то можно ограничиться релизной, но тогда мы получим лишь название функции, в которой слетело приложение (при не слишком глубоком анализе).

Теперь у нас есть дамп, его нужно проанализировать. Это очень просто, тут поможет отладчик gdb, команда: gdb полный_путь_к_бинарнику полный_путь_к_дампу, отладчик покажет место слёта (функцию, или вообще строчку кода для отладочной версии бинарника). Дамп должен соответствовать бинарнику, иначе можно получить непонятную фигню (то есть бинарник должен быть именно тот, на котором был получен дамп).

Полезные приёмы при работе в gdb.
1) Команда bt покажет стек вызова функций.
2) Если нажать ctrl-X, затем 1, то будет показан красивый листинг с указанием места слёта.
3) Командой print <имя переменной> можно посмотреть значения переменных на момент слёта.
4) dead0k советует делать не просто отладочную сборку (флаг -g), а добавить флаг -ggdb, я пока не пробовал, но стоит обратить внимание на этот совет.

Также дамп можно открыть в среде QtCreator, для этого выбираем в меню Отладка -> Начать отладку -> Загрузить файл дампа (Debug -> Start debug -> Load dump file). Qt покажет слёт "красиво", как будто мы его словили в отладчике (но только для отладочной версии приложения, в противном случае будет дизассемблер).

Также для дополнительной информации гуглить: linux core files, gdb, core files, thread sanitizer (собственно, по этим ключевым словам, следуя совету niXman, я и получил массу полезной информации).
Re: Анализ дампа с целью поиска segfault
Спасибо всем отозвавшимся. Каждый ответ оказался очень полезен. Дампы сделаны, разобраны, ошибка успешно найдена.

Чтобы подвести небольшой итог, сделаю ответ, собирающий все рекомендации, на случай если кто-то будет читать тему.

Итак, ситуация — есть слёт, который не выходит поймать в отладчике, но поймать очень хочется. Система linux debian, но думаю, это подойдёт для любого линукса.

Сначала нужно получить дамп. Для этого следуем инструкции по ссылке:
. Там достаточно понятно описано, как включить сброс дампов при слётах процессов. Единственное, на что нужно обратить особое внимание — у меня почему-то максимальный размер дампа после простоя системы сбрасывался на 0, так что имеет смысл периодически мониторить его значение и при необходимости выставлять обратно в unlimited: -ulimit -c, ulimit -c unlimited .

Обратите внимание, что дамп создаётся не при любом слёте, есть список сигналов аварийного завершения, при некоторых из них дампа не будет. Если приложение слетает, а дамп ни в какую не появляется, возможно, это именно такой сигнал. Рекомендую попробовать написать небольшую програмку, которая при запуске слетает по segfault (разыменуйте нулевой указатель), и проверьте, что она сбрасывает дамп, если дампа и с ней не будет, значит проблемы с настройкой дампов, если она дамп даёт, а ваше приложение — нет, то приложение было завершено сигналом, который не делает дамп (SigTerm кажется один из таких, список можно найти гуглением).

Также у нас при тесте один раз почему-то дампы перестали сбрасываться (даже у тестовой слётной программы), хотя ограничение стояло unlimited, после перезагрузки компа всё нормально заработало, возможно это был глюк, пока не разбирались.

Итак, по инструкции включаем дампы, затем запускаем приложение и добиваемся слёта. При слёте в выбранном каталоге появится файл core.Name.12345, здесь Name — название бинарника, 12345 — id процесса. Этот файл и есть наш дамп. Здесь нужно обратить внимание на один момент, приложение можно скомпилировать в релизной сборке, либо в отладочной сборке, лучше в отладочной, тогда анализ дампа сможет показать прямо строку в коде, в которой произошёл слёт, если отладочная сборка не падает, то можно ограничиться релизной, но тогда мы получим лишь название функции, в которой слетело приложение (при не слишком глубоком анализе).

Теперь у нас есть дамп, его нужно проанализировать. Это очень просто, тут поможет отладчик gdb, команда: gdb полный_путь_к_бинарнику полный_путь_к_дампу, отладчик покажет место слёта (функцию, или вообще строчку кода для отладочной версии бинарника). Дамп должен соответствовать бинарнику, иначе можно получить непонятную фигню (то есть бинарник должен быть именно тот, на котором был получен дамп).

Полезные приёмы при работе в gdb.
1) Команда bt покажет стек вызова функций.
2) Если нажать ctrl-X, затем 1, то будет показан красивый листинг с указанием места слёта.
3) Командой print <имя переменной> можно посмотреть значения переменных на момент слёта.
4) dead0k советует делать не просто отладочную сборку (флаг -g), а добавить флаг -ggdb, я пока не пробовал, но стоит обратить внимание на этот совет.

Также дамп можно открыть в среде QtCreator, для этого выбираем в меню Отладка -> Начать отладку -> Загрузить файл дампа (Debug -> Start debug -> Load dump file). Qt покажет слёт "красиво", как будто мы его словили в отладчике (но только для отладочной версии приложения, в противном случае будет дизассемблер).

Также для дополнительной информации гуглить: linux core files, gdb, core files, thread sanitizer (собственно, по этим ключевым словам, следуя совету niXman, я и получил массу полезной информации).