web-dev-qa-db-ja.com

セグメンテーション違反とは何ですか?

セグメンテーション違反とは何ですか? CとC++では違いますか?セグメンテーションフォルトとダングリングポインタはどのように関連していますか?

502
Rajendra Uppal

セグメンテーションフォールトは、「自分のものではない」メモリにアクセスすることによって発生する特定の種類のエラーです。セグメンテーション違反が発生したときはいつでも、メモリに問題があることを知っています。すでに解放されている変数へのアクセス、メモリの読み取り専用部分への書き込みなどです。メモリ管理に関しては、CとC++のセグメンテーション違反の間に主な違いはありません。

少なくともC(++)などの低級言語では、セグメンテーション違反を起こす方法はたくさんあります。セグメンテーションフォールトを取得する一般的な方法は、nullポインタを間接参照することです。

int *p = NULL;
*p = 1;

読み取り専用としてマークされたメモリの一部に書き込もうとすると、別のセグメンテーション違反が発生します。

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

ダングリングポインターは、以下のように、もう存在しないものを指しています。

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

ポインタpがぶら下がるのは、ブロックの終了後に存在しなくなった文字変数cを指すためです。あなたは(*p='A'のように)間接参照ダングリングポインタにしようとしたときに、あなたはおそらくセグメンテーション違反になるだろう。

590
zoul

それは単に不可能であるので、セグメンテーションフォールトが別のプロセスメモリに直接アクセスすることによって引き起こされないことは注目に値するでしょう(これは私が時々聞いているものです)。仮想メモリでは、すべてのプロセスが独自の仮想アドレス空間を持ち、任意の値のポインタを使用して別のプロセスにアクセスすることはできません。これに対する例外は、(おそらく)異なる仮想アドレスにマッピングされた同じ物理アドレス空間と、すべてのプロセスで同じ方法でマッピングされたカーネルメモリ(syscallでのTLBフラッシュを回避するために)です。そしてshmatのようなものです;) - これらは私が「間接的な」アクセスとして数えるものです。しかし、それらが通常プロセスコードから遠く離れていて、我々が通常それらにアクセスできることを確認することができます(それがそこにある理由ですが、それでも不適切な方法でそれらにアクセスするとセグメンテーションフォルトが発生します)。

それでも、不適切な方法で私たち自身の(プロセス)メモリにアクセスした場合(たとえば、書き込み不可の領域に書き込もうとした場合)、セグメンテーション違反が発生する可能性があります。しかし、その最も一般的な理由は、仮想アドレス空間の マッピングされていない という部分へのアクセスが物理的なアドレスにまったくないことです。

そしてこれはすべて仮想メモリシステムに関するものです。

101

セグメンテーションフォールトは、プロセスがその記述子テーブルにリストしていないページに対する要求、またはリストしていないページに対する無効な要求(たとえば、読み取り専用ページに対する書き込み要求)によって引き起こされる。

ダングリングポインターは、有効なページを指している場合も指していない場合もありますが、「予期しない」メモリセグメントを指しているポインターです。

正直に言うと、他のポスターが言及しているように、ウィキペディアにはこれに関する非常に良い記事があります だからそこを見てください 障害。

C、C++、またはポインターを許可する他の言語でも違いはありません。これらの種類のエラーは、通常、

  1. 適切に初期化される前に使用される
  2. それらが指すメモリが再割り当てまたは削除された後に使用されます。
  3. インデックスが配列の境界外にあるインデックス付き配列で使用されます。これは一般的に、STL/Boostベースのコレクション(C++)ではなく、従来の配列またはc-stringでポインター計算を行う場合のみです。
27
Component 10

ウィキペディアによると:

セグメンテーションフォルトは、プログラムがアクセスを許可されていないメモリ位置にアクセスしようとした場合、または許可されていない方法でメモリ位置にアクセスしようとした場合(たとえば、読み取り専用の場所への書き込みなどオペレーティングシステムの一部を上書きします。

15
Orhan Cinar

セグメンテーションエラー はハードウェア障害、この場合はRAMメモリによっても発生します。これはそれほど一般的ではない原因ですが、コードにエラーが見つからない場合は、おそらくmemtestが役に立ちます。

この場合の解決策は、RAMを交換してください。

編集:

ここに参照があります: ハードウェアによるセグメンテーション障害

11
Alejo Bernardin

セグメンテーションフォルト (プロセスの実行中のインスタンス)プロセスが他のプロセスによって使用されている読み取り専用メモリアドレスまたはメモリ範囲にアクセスしようとしているか、存在しない(無効)メモリアドレスにアクセスしようとしている。 ダングリングリファレンス(ポインタ)問題 は、内容が既にメモリから削除されているオブジェクトまたは変数にアクセスしようとしていることを意味します。

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here
7
Sohail xIN3N

ウィキペディアの Segmentation_fault ページには、その原因と理由を指摘した、とても素晴らしい説明があります。詳細な説明についてはWikiを調べてください。

コンピューティングでは、セグメンテーション違反(セグメンテーション違反に短縮されることが多い)またはアクセス違反は、メモリ保護を備えたハードウェアによって発生する障害であり、オペレーティングシステム(OS)にメモリアクセス違反について通知します。

以下は、セグメンテーション違反のいくつかの典型的な原因です。

  • NULLポインタの参照解除 - これはメモリ管理ハードウェアによって特別なケースになります
  • 存在しないメモリアドレス(外部プロセスのアドレス空間)にアクセスしようとしています
  • プログラムがメモリにアクセスしようとしています(プロセスコンテキストでのカーネル構造など)。
  • 読み取り専用メモリ(コードセグメントなど)に書き込もうとしています

これらは順番に無効なメモリアクセスをもたらすプログラミングエラーによって引き起こされます。

  • 初期化されていないポインタ(ワイルドメモリ、ランダムメモリアドレスを指す)への参照解除または割り当て

  • 解放されたポインタの参照解除または割り当て(解放された、解放された、または削除されたメモリを指すダングリングポインタ)

  • バッファオーバーフロー.

  • スタックオーバーフロー.

  • 正しくコンパイルされないプログラムを実行しようとしました。 (一部のコンパイラは、コンパイル時エラーがあっても実行可能ファイルを出力します。)

5
Roy

簡単に言うと、セグメンテーションフォルトは、オペレーティングシステムが不正なメモリアクセスを検出したことを示す信号をプログラムに送信し、メモリの破損を防ぐためにプログラムを早期に終了させることです。

3
FilipeCanatto

答えには「セグメンテーションフォルト」のいくつかの良い説明がありますが、セグメンテーションフォルトではメモリの内容がダンプされることが多いので、 「セグメンテーションフォルト」の部分の関係を共有したいダンプされた) そしてメモリは

半導体メモリが登場する前の1955年から1975年頃まで、コンピュータメモリの主要技術は銅線に張られた小さな磁気ドーナツを使用していました。ドーナツは「フェライトコア」と呼ばれ、メインメモリは「コアメモリ」または「コア」と呼ばれていました。

ここから から撮った。

1
Viktor Nonov

プログラムが存在しないメモリ位置にアクセスしようとしたとき、または許可されていない方法でメモリ位置にアクセスしようとしたときに、セグメンテーション違反またはアクセス違反が発生します。

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

ここでi [1000]は存在しないので、セグメンテーションフォルトが発生します。

セグメンテーションエラーの原因:

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers – this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside process’s address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).
0
Mohit Rohilla

「セグメンテーション違反」とは、アクセスできないメモリにアクセスしようとしたことを意味します。

最初の問題はあなたのmainの議論にあります。 main関数はint main(int argc、char * argv [])でなければならず、argv [1]にアクセスする前にargcが2以上であることを確認する必要があります。

また、printfにfloatを渡しているので(ところで、printfに渡すとdoubleに変換されます)、フォーマット指定子は%fを使用する必要があります。 %sフォーマット指定子は文字列用です( '\ 0'で終わる文字配列)。

0
PHP Worm...