Segmentation fault(NULLポインタの参照)
NULL(何も指していないポインタ)の指す先を読み書きしようとしたときに発生するクラッシュです。Cで最も頻出する実行時エラーです。
エラーメッセージの読み方
Segmentation fault
(エラーメッセージなし)- これはプログラム自身の出力ではありません。プログラムは何も言わずに落ちています
Segmentation fault- シェルが検知した異常終了の種類 — OSが「不正なメモリアクセス」などを検出しプロセスを強制終了させました
見つけ方- このメッセージだけでは行番号すら分かりません。原因はコードを読んで特定するしかありません
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) { 5 int *p = NULL ; ^ 6 printf("%d\n", *p); 7 return 0; 8 }
Segmentation fault
NULLは「何も指していない」という印です。*pでその指す先を読もうとした瞬間、無効なアドレスへのアクセスとしてクラッシュします。
直し方: NULL を malloc(sizeof(int)) にします。
広告
広告スロット(未設定)
パターン2
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) { 5 int value = 7; 6 int *p = NULL ; ^ 7 *p = value; 8 printf("%d\n", *p); 9 return 0; 10 }
Segmentation fault
pがNULLのまま*p = valueで書き込もうとすると、読み込みと同様にクラッシュします。有効な変数のアドレス(&value)を指すようにする必要があります。
直し方: NULL を &value にします。
パターン3
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) { 5 int *p = malloc(sizeof(int)); 6 p = NULL ; ^ 7 *p = 1; 8 printf("%d\n", *p); 9 return 0; 10 }
Segmentation fault
せっかくmallocで有効な領域を確保していても、途中でpにNULLを代入し直すと、その後の*pは無効な参照になります。
直し方: NULL を p にします。
よくある誤解
NULLを代入した行では何も起きません。実際にそのポインタを*pや->で参照した瞬間にクラッシュします。関数がNULLを返す可能性がある場合(mallocの失敗など)、使う前にNULLチェックをしないと危険です。
まとめ
Segmentation fault(NULLポインタの参照)は初級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。