2012年6月7日木曜日

Segmentation fault の原因

コンパイルは通ったのに,いざ実行してみたら"Segmentation fault"の表示.
誰でも一度は通る道だと思います.

慣れてくると,どうやってバグを取り除けばいいかわかってくるかと思いますが,
その原因となることを幾つか紹介していきます.

1,確保していない領域を使おうとしている

これが,ほぼすべての"Segmentation fault"の原因であると思います.
こんなことを書いちゃうと発生します.

int array[10];
array[15] = 20;

これは明らかに確保していない領域を使おうとしていますよね.
こんな場合だとすぐに見つけられると思いますが,たくさんの配列を使用していて,
forループで内容をいじっている場合などは問題に気づきにくい場合があります.
また,そのforループ自体では"Segmentation fault"が発生せず,不正利用している
アドレスに他のデータが重ならないとエラーが出ない場合があります.
例えば,N=50の時にはエラーが出なかったのに,N=5000にしたら"Segmentation fault"
が発生する.といった具合です.
そうなってしまったら,gdbコマンドや"printf()"を駆使して,
どこでエラーが発生するのか頑張って探しましょう.
基本的には"Segmentation fault"が発生している部分の"前"で
間違いを犯しているはずです.


2,2次元配列などでかなり大きな領域を確保しようとする

こちらは"Segmentation fault"が発生する位置が,問題を起こしている部分より"前"
にくる可能性があって,気をつけなければならないエラーとなります.
エラー自体は単純なもので,二次配列(またはそれ以上)の形で,
大変大きな領域を確保しようとした場合に発生します.

int matrix[3000][2000];

こんな具合で大きな領域を確保しようとした場合に,"Segmentation fault"が
発生します.
この解決法は単純で,配列の領域確保を"動的配列(malloc, calloc)"
で確保してやれば大丈夫です.

int **matrix;
int row = 3000, column = 2000, i;

matrix = (int **)malloc(sizeof (int*) * row);
for(i = 0; i < row; i++){
   matrix[i] = (int *)malloc(sizeof (int) * column);
}

これで解決するのですが,"Segmentation fault"が発生する部分より後ろ,
具体的には,関数内において,

void func(...){
printf("check\n");

int matrix[3000][2000];
...
}

と書いた場合に,"check"が表示されずに"Segmentation fault"が発生してしまいます.
これは,1.で示したように"前"の部分を探しても発見できず,発見が遅れるバグです.
気をつけてください.









0 件のコメント :

コメントを投稿