Можете ли вы получить какую-либо программу для Linux, чтобы распечатать трассировку стека, если она segfaults?
Если я запускаю программу из оболочки, и она segfaults:
$ buggy_program
Segmentation fault
Это скажет мне, однако, есть ли способ заставить программы печатать обратную трассировку, возможно, запустив что-то вроде этого:
$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)
Я также предпочел бы не использовать strace или ltrace для такой информации, поскольку они будут печататься в любом случае...
6 ответов
Возможно, есть лучший способ, но этот тип автоматизирует его.
Поместите следующее в ~/backtrace
:
backtrace
quit
Поместите это в скрипт seg_wrapper.sh
в каталоге на вашем пути:
#!/bin/bash
ulimit -c unlimited
"$@"
if [[ $? -eq 139 ]]; then
gdb -q $1 core -x ~/backtrace
fi
ulimit
команда делает так, чтобы ядро было сброшено. "$@"
это аргументы, данные скрипту, поэтому это будет ваша программа и ее аргументы. $?
содержит состояние выхода, 139, по-видимому, состояние выхода по умолчанию для моей машины для segfault.
За gdb
, -q
означает тихий (без вступительного сообщения), и -x
говорит gdb
выполнять команды в данном файле.
использование
Таким образом, чтобы использовать его, вы просто:
seg_wrapper.sh ./mycommand and its arguments
Обновить
Вы также можете написать обработчик сигнала, который делает это, см. Эту ссылку.
Извините, что приехал сюда через 2 года... наткнулся, когда искал что-то еще. Добавим это для полноты.
1) Хотя я думаю, что принятый ответ отличный, он требует GDB. Метод, с которым я знаком, использует libSegFault.so.
Если вы запустите свое приложение с
LD_PRELOAD=... путь к.../libSegFault.so myapp
Вы получите отчет с трассировкой, загруженными библиотеками и т. Д.
2) скрипт-обёртка catchsegv
также доступно, что будет пытаться использовать addr2line
перевести адреса в имя файла + номер строки.
Это гораздо более легкие решения, чем файлы core или gdb (например, хорошо для встроенных систем)
Это было упомянуто в другом ответе (но никоим образом не сфокусировано на). Это удобный инструмент в комплекте с проектом glibc. Он обеспечит обратную трассировку (и другую полезную отладочную информацию), только если программа действительно выполняет segfault.
Хорошая статья существует здесь.
Вы можете включить его в свои сценарии по своему усмотрению.
Тебе нужен друг каждого GDB
gdb <program> [core file]
После того, как вы загрузили свой основной файл, команда 'backtrace' (сокращенно bt) выдаст вам текущий стек вызовов. Если вы запускаете свою программу изнутри GDB, вы можете установить произвольные точки останова, проверить содержимое памяти и т. Д.
Ubuntu (как проект) использует Apport для этого. Вы можете посмотреть, как они это сделали.
Вот слегка модифицированный вариант сценария от Кайла Брандта. Это улучшено следующими способами:
- не требует ручного взаимодействия, если трассировка стека длинная
- некоторые coredumps сохраняются с именем шаблона ядра., соблюдайте этот параметр
- не требует явного командного файла для GDB (он создаст временный)
- ждать фоновых заданий
Автор сценария:
#!/bin/bash
gdbcommandfile=$(tempfile)
usepid=$(cat /proc/sys/kernel/core_uses_pid)
printf "set pagination off\nbacktrace\nquit\n" > $gdbcommandfile
ulimit -c unlimited
"$@"&
pid=$!
wait $!
if [[ $? -eq 139 ]]; then
if [[ $usepid == 1 ]]; then
gdb -q $1 core.$pid -x $gdbcommandfile
else
gdb -q $1 core -x $gdbcommandfile
fi
fi
rm $gdbcommandfile