C言語 Segmentation fault(セグメンテーション違反)の原因と解決策
最終更新日: 2026-08-27
30秒でわかる原因と解決策
原因: プログラムが許可されていないメモリ領域(存在しないアドレスや読み取り専用領域)にアクセスしようとしたこと。主に、未初期化のポインタの参照、NULLポインタのデリファレンス、配列の範囲外アクセス、スタックオーバーフローなどが原因となります。 解決策: デバッガー(GDBなど)やアドレスサニタイザー(
-fsanitize=address)を使用してエラー発生箇所を特定し、ポインタの有効性確認や適切なメモリ割り当て(malloc等)、配列の境界チェックを行います。
修正コード(Before / After)
❌ エラーが発生するコード
#include <stdio.h>
int main(void) {
int *ptr; // ポインタが初期化されていない(ゴミ値が入っている)
*ptr = 10; // 不正なメモリアドレスに書き込もうとしてSegmentation faultが発生
printf("%d\n", *ptr);
return 0;
}
⭕ 修正後の推奨コード
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// メモリを動的に割り当てる、または有効な変数のアドレスを代入する
int *ptr = (int *)malloc(sizeof(int));
if (ptr == NULL) {
fprintf(stderr, "メモリの割り当てに失敗しました\n");
return 1;
}
*ptr = 10; // 正しく割り当てられたメモリ領域に書き込む
printf("%d\n", *ptr);
free(ptr); // 使用後は必ず解放する
ptr = NULL; // ダングリングポインタを防ぐためNULLを代入
return 0;
}
よくある発生パターンと解説
C言語における Segmentation fault(セグメンテーション違反) は、プログラマが意図しないメモリ領域にアクセスした際に、OSがプロセスを強制終了させることで発生します。代表的な発生パターンは以下の4つです。
1. ポインタの初期化忘れとワイルドポインタ
宣言しただけのポインタ変数には、不定値(ゴミ値)が入っています。これをそのままデリファレンス(*ptr)すると、関係ないメモリ領域を指してしまいエラーになります。必ず有効なアドレスを代入するか、NULLで初期化してください。
2. NULLポインタの参照(Dereference)
NULL(アドレス0)が格納されたポインタに対して値の代入や参照を行うと発生します。動的メモリ確保(mallocなど)の失敗チェックを怠ると、このエラーに直結します。
3. 配列の範囲外アクセス(Out-of-bounds)
要素数が10の配列に対して arr[10] や arr[100] のように範囲外のインデックスを指定した場合、隣接する重要なメモリ領域を破壊またはアクセスしようとしてSegmentation faultを引き起こします。
4. 文字列リテラルの書き換え
char *str = "Hello";
str[0] = 'h'; // 読み取り専用領域を変更しようとしてエラー
文字列リテラルは通常、メモリ上の読み取り専用セクションに配置されるため、書き換えようとするとクラッシュします。文字配列として宣言 (char str[] = "Hello";) する必要があります。
よくある質問 (FAQ)
Q1. エラーが発生した正確な行数を特定するにはどうすればよいですか?
A. コンパイル時に -g オプションを付けてデバッグ情報を付加し、gdbなどのデバッガーで実行してください。
gcc -g program.c -o program
gdb ./program
(gdb) run
実行が停止した行(btコマンドでバックトレースも確認可能)で原因箇所が分かります。また、ClangやGCCであれば -fsanitize=address オプションが非常に有効です。
Q2. -fsanitize=address とは何ですか?
A. アドレスサニタイザー(AddressSanitizer)という機能です。コンパイル時にコードを埋め込み、メモリの範囲外アクセスや解放済みメモリへのアクセスを検知した際、分かりやすいエラーメッセージとスタックトレースを出力してくれます。
gcc -fsanitize=address -g program.c -o program
./program
開発時は常にこのオプションを有効にすることをお勧めします。