Segmentation fault(配列の範囲外への書き込み)
配列の宣言サイズを大きく超えた添字に書き込むと、プロセスに割り当てられていないメモリ領域に触れてクラッシュします。
エラーメッセージの読み方
Segmentation fault
(エラーメッセージなし)- これはプログラム自身の出力ではありません。プログラムは何も言わずに落ちています
Segmentation fault- シェルが検知した異常終了の種類 — OSが「不正なメモリアクセス」などを検出しプロセスを強制終了させました
見つけ方- このメッセージだけでは行番号すら分かりません。原因はコードを読んで特定するしかありません
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 3 int main(void) { 4 int scores[5] = {1, 2, 3, 4, 5}; 5 scores[100000000] = 99; ^ 6 printf("%d\n", scores[0]); 7 return 0; 8 }
Segmentation fault
配列の宣言サイズを大きく超えた添字に書き込むと、プロセスに割り当てられていないメモリ領域に触れてクラッシュします。
直し方: 100000000 を 0 にします。
広告
広告スロット(未設定)
パターン2
1 #include <stdio.h> 2 3 int main(void) { 4 int data[10]; 5 data[999999999] = 1; ^ 6 printf("%d\n", data[0]); 7 return 0; 8 }
Segmentation fault
少しだけ超えた添字は近くの別の変数を静かに破壊するだけでクラッシュしないこともありますが、大きく外れた添字ではOSがメモリ保護違反として検出しクラッシュさせます。
直し方: 999999999 を 0 にします。
パターン3
1 #include <stdio.h> 2 3 int main(void) { 4 int buffer[3]; 5 buffer[50000000] = 5; ^ 6 printf("%d\n", buffer[0]); 7 return 0; 8 }
Segmentation fault
配列が小さいほど、少し大きめの添字を渡しただけでもプロセスの外の領域に触れやすくなります。
直し方: 50000000 を 0 にします。
よくある誤解
「範囲外アクセスは必ずクラッシュする」わけではありません。少しだけ超えた場合は近くの別の変数を静かに破壊するだけでクラッシュしないこともあります(発見はむしろこちらの方が困難です)。大きく外れた添字の場合にのみ、OSがメモリ保護違反として検出しクラッシュさせます。
まとめ
Segmentation fault(配列の範囲外への書き込み)は上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。