Можете ли вы получить какую-либо программу для Linux, чтобы распечатать трассировку стека, если она segfaults?


20

Если я запускаю программу из оболочки, и она segfaults:

$ buggy_program
Segmentation fault

Это скажет мне, однако, есть ли способ заставить программы печатать обратную трассировку, возможно, запустив что-то вроде этого:

$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)

Я также предпочел бы не использовать strace или ltrace для такой информации, поскольку они будут печататься в любом случае ...

Ответы:


25

Возможно, есть лучший способ, но этот тип автоматизирует его.

Поместите следующее в ~/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
вы, вероятно, имеете в виду «-x говорит GDB выполнить» вместо «-x указывает GDB на выход»
josch

19

Извините, что приехал сюда через 2 года ... наткнулся, когда искал что-то еще. Добавим это для полноты.

1) Хотя я думаю, что принятый ответ отличный, он требует GDB. Метод, с которым я знаком, использует libSegFault.so.

Если вы запустите свое приложение с

LD_PRELOAD = ... путь к ... / libSegFault.so myapp

Вы получите отчет с трассировкой, загруженными библиотеками и т. Д.

2) catchsegvТакже доступен скрипт-обертка , который попытается использовать addr2lineдля перевода адресов в имя файла + номер строки.

Это гораздо более легкие решения, чем файлы core или gdb (например, хорошо для встроенных систем)


На самом деле, LD_PRELOAD=libSegFault.soхорошо, если он находится в пути DL.
Фернандо Сильвейра

1
@FernandoSilveira хорошо. Написание ответа таким образом намекает читателю, что он должен проверить, что это за путь.
nhed

6

Тебе нужен друг каждого GDB

gdb <program> [core file]

После того, как вы загрузили свой основной файл, команда 'backtrace' (сокращенно bt) выдаст вам текущий стек вызовов. Если вы запускаете свою программу изнутри GDB, вы можете установить произвольные точки останова, проверить содержимое памяти и т. Д.


Есть ли способ заставить его просто распечатать след и выйти?
Нил

5

catchsegv

Это было упомянуто в другом ответе (но никоим образом не сфокусировано на). Это удобный инструмент в комплекте с проектом glibc. Он обеспечит обратную трассировку (и другую полезную отладочную информацию), только если программа действительно выполняет segfault.

Хорошая статья существует здесь .

Вы можете включить его в свои сценарии по своему усмотрению.



2

Вот слегка модифицированный вариант сценария от Кайла Брандта. Это улучшено следующими способами:

  • не требует ручного взаимодействия, если трассировка стека длинная
  • некоторые 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

1
Для цепочки таких простых команд я бы просто использовал -exвместо этого. gdb ... -ex 'set pagination off' -ex backtrace -ex quit
Джош Стоун
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.