コア
多くのシステムにはgcoreというコマンドがあって,それを使用すると指定したプロセスのコアファイルを取得できるらしい.GNU/Linuxシステム(少なくとも私のマシン)には,gcoreはないが,gdbを使用すると容易にコアファイルを取得できる.さらにgdbにコアファイルを渡すことで,ダンプ時点のプロセスの状態を調べることができる.
コアファイルは,プロセスのメモリダンプである.当然ダンプするタイミングによって内容は変わる.で,コアを使用することで,ダンプした時点での,プロセスの各変数の内容やスタックなどの情報を入手できる.要するにコアはデバッグに有用な情報を提供してくれる.
gdbでは
まず-gをつけてコンパイルし,gdbを起動.そして10行目にブレークポイントを設定して実行.
generate-core-fileでコアを吐ける.以下のサンプルを使用して実際にやってみる.
> gcc -g hoge.c > gdb a.out (gdb) break 10 (gdb) run Breakpoint 1, main (argc=1, argv=0xbffff6b4) at hoge.c:11 11 fprintf (stdout, "hoge %d\n", i); (gdb) print i $1 = 0iは今0である.で,適当に何回かcontinueしてみる.今回はi=5でブレークした状態でコアを吐いてgdbを終了する.
(gdb) generate-core-file Saved corefile core.1676今回はcore.1676というコアファイルが出力された.
> ls core* core.1676で,このコアファイルを使用してgdbを起動.
> gdb a.out core.1676 ...省略... #0 main (argc=1, argv=0xbffff6b4) at hoge.c:11 11 fprintf (stdout, "hoge %d\n", i); (gdb) print i $1 = 5いろいろと出力されて,ダンプ時点のプロセスの状態が再現される.実際iの値は5である.
上の例はどうも引っかかる.コアファイルと-g付きでコンパイルされた実行ファイルがあれば,gdbでのデバッグ作業がかなり楽になる.再現性の低い障害の場合は特に.問題はコアファイルの生成である.gdbで起動してgenerate-core-fileを実行するというのは,後で再現したい場合や,止められないシステムなどにそれなりに有用ではあるが,あまり意味がないように思える(その場でデバッグすればよい).プログラムの状態に応じてgdbに依存しない形でプログラムが自発的にコアを吐いてくれる仕組みが必要なのである.man 7 signalによると,SIGQUIT,SIGILL,SIGABRTなどを受信したプロセスはコアを吐いて終了するとある.さらに
> ulimit -cでコアファイルサイズの最大値が分かる.私のシステムでは0に設定されていて,(一般ユーザでは)2以上には設定できないようになっていた(※).このあたりの設定を変更してプログラムの適当な場所でabortなどするとコアが吐かれるだろうか(なんかうまくいかない).
※プロセスのメモリをそのままダンプするコアには,プロセスによってはパスワード情報などが含まれる場合がある.この問題を再優先に考えるなら,この設定は妥当だろう.だいたいコアは開発したりバグレポートしたりしない人には無用である.

