Если я запускаю программу из оболочки, и она перестает работать:
$ buggy_program
Segmentation fault
Однако он скажет мне, есть ли способ заставить программы печатать обратную трассировку, возможно, запустив что-то вроде этого:
$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)
Я бы также предпочел не использовать strace или ltrace для такого рода информации, поскольку они будут печатать в любом случае ...
Может быть способ получше, но он автоматизирует его.
Поместите следующее в ~/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
для преобразования адресов в имя файла + номер строки.
Это гораздо более легкие решения, чем файлы ядра или gdb (например, подходят для встроенных систем)
Вам нужен друг GDB
gdb <program> [core file]
После того, как вы загрузили свой corefile, команда backtrace (может быть сокращена до bt) предоставит вам текущий стек вызовов. Если вы запустите свою программу изнутри gdb, вы можете установить произвольные точки останова, проверить содержимое памяти и т. Д.
Это упоминалось в другом ответе (но никоим образом не касалось). Это удобный инструмент, входящий в состав проекта glibc. Он предоставит обратную трассировку (и другую полезную отладочную информацию) только если программа действительно делает ошибку segfault.
Хорошая запись существует Вот.
Вы можете включить его в свои собственные скрипты по своему усмотрению.
Ubuntu (как проект) использует для этого Apport. Вы можете посмотреть, как они это сделали.
Вот немного измененный вариант сценария от Кайла Брандта. Его улучшают следующими способами:
#!/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