C/C++のコードを書いてよく遭遇するのがSegmentation Fault、通称セグフォ。その傾向と対策をまとめてみた。
傾向
セグフォがよく起こるのは以下のとき。
メモリ違反
見てはいけないメモリ領域を参照したときに起こる。コード例は以下。
#include <stdio.h> int main(){ int array[10]; int i; for(i = 0; i < 20; ++i){ array[i] = i; } return 0; }
対策1:セグフォの発生場所を特定する
セグフォを起こした場所を特定するには、ダンプされたcoreを使うとよい。
coreを出力
まず、コアファイルが出力される設定になっているか確認する。
$ ulimit -c
して、0が表示されるようであれば以下のコマンドを実行する。これでコアファイルが出力される。
$ ulimit -c unlimited
実行
実行ファイルを実行するとcore.(プロセス番号)が出力される。
$ ./a.out
デバッグ
コアファイルを使って、どこでセグフォが起きたかを特定する。
$ gdb a.out core.(プロセス番号)
よく使うコマンドは以下。
- backtrace
- 関数の呼び出し順を確認
- frame n
- backtraceで表示されている関数のうち、n番目の関数に移動
- info locals
- ローカル変数の一覧を確認
- info args
- 引数の一覧を確認
- print val
- 変数valの値を表示
対策2:スタックサイズを変更する
再帰が深すぎるためにセグフォが発生している場合は、スタックサイズを変更することでセグフォを回避できることがある。
例えばgccの場合は以下のようにしてスタックサイズを変更できる。
gcc -Wl,--stack,4194304 program.c
Visual Studio 2013 の場合は、プロジェクトのプロパティ→リンカー→システム→スタックのサイズの設定 に適切な値を入力することでスタックサイズを変更できる。