Code Fix

上級

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

配列の宣言サイズを大きく超えた添字に書き込むと、プロセスに割り当てられていないメモリ領域に触れてクラッシュします。

直し方: 1000000000 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン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がメモリ保護違反として検出しクラッシュさせます。

直し方: 9999999990 にします。

この問題を解いてみる →

パターン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

配列が小さいほど、少し大きめの添字を渡しただけでもプロセスの外の領域に触れやすくなります。

直し方: 500000000 にします。

この問題を解いてみる →

よくある誤解

「範囲外アクセスは必ずクラッシュする」わけではありません。少しだけ超えた場合は近くの別の変数を静かに破壊するだけでクラッシュしないこともあります(発見はむしろこちらの方が困難です)。大きく外れた添字の場合にのみ、OSがメモリ保護違反として検出しクラッシュさせます。

まとめ

Segmentation fault(配列の範囲外への書き込み)は上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)