Segmentation fault(scanfで&を付け忘れる)
scanfは書き込み先のアドレスを受け取る関数です。scanf("%d", x)のように&を付け忘れると、変数の値そのものを不正なアドレスとして書き込もうとし、クラッシュします。
エラーメッセージの読み方
Segmentation fault
(エラーメッセージなし)- これはプログラム自身の出力ではありません。プログラムは何も言わずに落ちています
Segmentation fault- シェルが検知した異常終了の種類 — OSが「不正なメモリアクセス」などを検出しプロセスを強制終了させました
見つけ方- このメッセージだけでは行番号すら分かりません。原因はコードを読んで特定するしかありません
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 3 int main(void) { 4 int age; 5 sscanf("42", "%d", age ); ^ 6 printf("%d\n", age); 7 return 0; 8 }
Segmentation fault
scanf系の関数は書き込み先のアドレスを受け取ります。&を付け忘れると、変数の値そのものを不正なアドレスとして書き込もうとしクラッシュします。
直し方: age を &age にします。
広告
広告スロット(未設定)
パターン2
1 #include <stdio.h> 2 3 int main(void) { 4 int score; 5 sscanf("100", "%d", score ); ^ 6 printf("%d\n", score); 7 return 0; 8 }
Segmentation fault
printfは値を読むだけなので変数名で足りますが、書き込みを行うscanf系の関数にはアドレス(&変数名)が必要です。
直し方: score を &score にします。
パターン3
1 #include <stdio.h> 2 3 int main(void) { 4 int count; 5 sscanf("7", "%d", count ); ^ 6 printf("%d\n", count); 7 return 0; 8 }
Segmentation fault
この非対称性(読むだけのprintfと書き込むscanf系)がscanfの&忘れを起こしやすくしています。標準入力から読むscanf自体でも同じ問題が起こります。
直し方: count を &count にします。
よくある誤解
printfとscanfは似た形をしていますが役割が逆です。printfは値を「読む」ので変数名だけでよく、scanfは値を「書き込む」ので書き込み先のアドレス(&変数名)が必要です。この非対称性が付け忘れの原因になります。
まとめ
Segmentation fault(scanfで&を付け忘れる)は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。