セグメンテーション違反
セグメンテーション違反(英語:segmentation fault)はソフトウェアの実行時に起きる特定のエラー条件である。segfault(セグフォールト)と略される場合がある。 セグメンテーション違反はアクセスが許可されていないメモリ上の位置、もしくは許可されていない方法(例えばリードオンリーの位置へ書き込みをしようとする、もしくはオペレーションシステムの部分を上書きしようとする)でメモリ上の位置にアクセスしようとするときに起こる。MC68000のようなプロセッサに基づくシステムはこれらのイベントをアドレスエラーもしくはバスエラーとして参照しようとする傾向にある。
セグメント方式はメモリ管理とオペレーティングシステムを保護する方法の一つである。大部分の用途のためにページング方式に置き換えられつつあるが、セグメンテーションの専門用語はまだ多く使用されている。セグメンテーション違反はその一例である。オペレーションシステムの中にはメインメモリ管理の方針としてページング方法が使用されているがいくつかの論理レベルでまだセグメンテーションを持つものがある。
UNIXライクのオペレーティングシステム上では、不正なメモリにアクセスをするプロセスはSIGSEGVシグナルを受け取る。Microsoft Windows上では、不正なメモリにアクセスするプロセスはSTATUS_ACCESS_VIOLATION例外を受け取る。
例
次のANSI C言語のコードはメモリ保護機能を持つプラットフォーム上でセグメンテーション違反を作り出す例である。
const char *s = "hello world";
*s = 'H';
このコードを含むプログラムがコンパイルされた時、"hello world"の文字列リテラルはリードオンリーとしてマークされたプログラムバイナリのセクションに置かれる; ロードされたとき、オペレーティングシステムはそれをリードオンリーのメモリーセグメントで他の文字列と定数データで置き換える。 実行されたとき、s変数は、文字列の位置を指定するように設定され、変数を通してH文字をメモリに書き込むことが企てられるが、結果はセグメンテーション違反が起こる。このようなプログラムをコンパイルして実行すると、例えば次のようなランタイムエラーを起こす:
$ gcc segfault.c -g -o segfault
$ ./segfault
Segmentation fault
以下はGNUデバッガからのスタックトレースである:
Program received signal SIGSEGV, Segmentation fault.
0x1c0005c2 in main () at segfault.c:6
6 *s = 'H';
一方で、Linux上のgcc 4.1.1はデフォルトでコンパイルタイムエラーを発生させる:
$ gcc segfault.c -g -o segfault
segfault.c: In function ‘main’:
segfault.c:4: error: assignment of read-only location
セグメンテーション違反が起こる条件とそれらをそれら自身で宣言する方法はオペレーションシステム特有のものである。
共通のプログラムエラーはNullポインタの参照外し(Nullポインタを通した読み込みもしくは書き込み、アドレス0へのアクセスはC言語で共通に使用され、"存在しないオブジェクトへのポインタ"もしくはエラーインディケータを意味する)であるので、大抵のオペレーションシステムはメモリの最初のページ(0アドレスで始まる)をマッピングしてそのページへのアクセスがセグメンテーション違反を引き起こす。
関連項目
- バッファオーバーラン
- バスエラー
- コアダンプ
- Segfault、このエラーの名前を取ったユーモアウェブサイト。