STDERRの下に「セグメントエラー」メッセージがありますか?

STDERRの下に「セグメントエラー」メッセージがありますか?

実行ファイルを実行しました。bash

./code > log

すべてのprintfステートメントがログファイルに移動している間、端末には時々エラーメッセージが表示されます。以下のようにやり直してください。

./code >& log

これで、時々発生するエラーメッセージも記録されます。ただし、分割エラーがある場合は端末に表示されます。なぜ?メッセージをSegmentation fault (core dumped)ログファイルに入れるにはどうすればよいですか?


ユーザー $bash --version

GNU bash、バージョン 4.2.24(1)-リリース(i686-pc-linux-gnu)

答え1

「セグメントエラー」メッセージはstderrに印刷されますが、これはプログラムの標準エラーではなく、シェルの標準エラーです。シェルは、プログラムが信号のために終了したことを検出すると、このメッセージを印刷します。

実行中のプログラムのシェルスクリプト部分の周りでstderrをリダイレクトすることで、このメッセージを無音に設定できます。

{ ./code; } >&log

答え2

スプリットエラーはシグナルであり、それをキャプチャできないとプログラムは終了し、シェルはそれを標準エラー(プログラムの標準エラーではない)として印刷します。

これが発生した場合、プログラムまたはシェルはプログラムにシグナルをキャプチャして特定のアクションを実行するか、シェルがSIGCHILDシグナルをキャプチャしてサブプロセスの終了ステータスを確認できます。

答え3

エラーメッセージはリダイレクトされますが、分割エラーがある場合にのみ端末に表示されます。なぜ?

Per GilesのTL / DR:分割エラーメッセージはプログラムで発生しないため、stderrこれらのstdoutメッセージをリダイレクトしても効果はありません。スプリットエラーメッセージは、スプリットエラーサブプロセスを実行するシェルによって生成されます。

後で起こるのは、サブプロセスが終了した後にシェルがwait()(またはwaitpid())を呼び出し、その応答を使用して、サブプロセスが信号の受信によって終了したことを確認することです。

その場合、シェルは通常メッセージを印刷しますが、必ずしもそうではありません。

trapシェルは魔法のように子供に死ぬという信号を送らないことに注意してください。子供だけが信号を捕捉したり、信号によって死亡したりすることができます。子が死亡すると、親はSIGCHLDを受け取りますが、これは別のシグナルです。

エラーメッセージを印刷または印刷しないことに加えて、シェルは示す終了$?ステータスも設定します。

$ ./div_by_0
Floating point exception
$ echo $?
136

ゼロ除算などの信号にも同様に適用されます。詳細についてはを参照してくださいman 3 wait

これによって発生する1つの結果は、子プロセスがプロセスチェーンの最後のプロセスである場合にのみメッセージを受信することです。

例えば

$ ./div_by_0
Floating point exception
$ echo | ./div_by_0
Floating point exception
$ ./div_by_0 | wc
0 0 0

Gilesによると、コマンド出力をファイルにキャプチャしても、シェルがメッセージを印刷するのを防ぐことはできません。

$ { ./div_by_0 ; } > log
Floating point exception
$ { ./div_by_0 ; } >& log
$ cat log
Floating point exception

ただし、コマンド出力を変数としてキャプチャすると、シェルがメッセージを印刷できなくなります。

$ a=$(./div_by_0)
$ echo $a
$

変数またはファイルの出力をキャプチャしても、出力が設定されるの$?を妨げません。

$ { ./div_by_0 ; } >& log
$ echo $?
136
$ a=`{ ./div_by_0 ; }`
$ echo $?
136

エラーメッセージで何をしたいかに応じて、上記の内容はすでにあなたのニーズに適している可能性があり、$?プログラムを呼び出した後に確認したい場合があります。

また、これを使用trap ERRしてエラーをキャッチしてからアクションを呼び出して、$?SIGSEGV、SIGFPE、または他のものと一致することを確認することもできます。

例えば

$ trap 'exit_code=$?; echo "exit code: $exit_code"; if [[ $exit_code -eq 139 ]]; then echo "segfault"; fi ; if [[ $exit_code -eq 136 ]] ; then echo "div by 0"; fi ;' ERR
$ ./div_by_0
Floating point exception
exit code: 136
div by 0

trapこの機能をオンにすると、設定する前にSIGCHLDトラップコードが$?呼び出されるため、目的の結果が出る可能性が低くなります。無効なコマンドは "$?" = 0を返すように見え、次のコマンドはゼロ以外の値を返すように見えます。$?

例えば

$ ./div_by_0
exit code: 0
Floating point exception
$ ./div_by_1
exit code: 136      <-- this is $? from div_by_0, not from div_by_1
div by 0

関連情報