Linuxでセグメンテーション違反が発生した場合にスタックトレースを出力するプログラムを入手できますか?


20

シェルからプログラムを実行すると、セグメンテーション違反が発生します。

$ 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は、セグメンテーション違反に対する私のマシンのデフォルトの終了ステータスのようです。

以下のためにgdb-q静かな(無イントロメッセージ)を意味し、-x伝えるgdbそれに与えられたファイル内のコマンドを実行します。

使用法

それを使用するには、次のようにします。

seg_wrapper.sh ./mycommand and its arguments 

更新

これを行うシグナルハンドラを記述することもできます。このリンクを参照してください


2
シグナルハンドラ・ソリューションへのあなたのリンクは死んでいる-の答えは、他のリソースにリンクすることはできません理由です...
josch

1
「-xはgdbに終了するように指示する」の代わりに、「
-josch 14

19

2年後にここに来て申し訳ありません...他のものを探している間につまずいた。完全を期すためにこれを追加します。

1)受け入れられた答えは素晴らしいと思いますが、gdbが必要です。私がよく知っている方法ではlibSegFault.soを使用します。

でアプリを実行する場合

LD_PRELOAD = ... path-to ... / libSegFault.so myapp

バックトレース、ロードされたライブラリなどを含むレポートを取得します

2)アドレスをファイル名+行番号に変換catchsegvするaddr2lineために使用するラッパースクリプトも利用できます。

これらはコアファイルやgdbよりもはるかに軽いソリューションです(たとえば、組み込みシステムに適しています)


実際、LD_PRELOAD=libSegFault.sodlパスにある場合は問題ありません。
フェルナンドシルベイラ

1
@FernandoSilveiraわかりました。このように答えを書くと、読者はそのパスが何であるかをチェックする必要があることを示唆します。
14

6

みんなの友達GDBが必要です

gdb <program> [core file]

コアファイルをロードしたら、コマンド「backtrace」(btと略すことができます)により、現在のコールスタックが表示されます。gdb内からプログラムを実行する場合、任意のブレークポイントを設定し、メモリの内容などを調べることができます。


バックトレースを出力して終了するだけで取得する方法はありますか?
ニール

5

catchsegv

別の回答で言及されました(しかし、決して焦点を当てていませんでした)。glibcプロジェクトにバンドルされている便利なツールです。プログラムが実際にセグメンテーション違反を起こした場合にのみ、バックトレース(およびその他の有用なデバッグ情報)を提供します。

ここに良い記事があります

必要に応じて、独自のスクリプトに含めることができます。



2

次に、Kyle Brandtのスクリプトを少し修正したバリアントを示します。次の点で改善されています。

  • スタックトレースが長い場合、手動での対話を必要としません
  • 一部のコアダンプは名前パターンコアで保存されます。この設定を尊重してください
  • 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
ジョシュストーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.