セグメンテーション違反とは何ですか?CとC ++では違いがありますか?セグメンテーション違反とぶら下がりポインタはどのように関連していますか?
NullPointerException
。
セグメンテーション違反とは何ですか?CとC ++では違いがありますか?セグメンテーション違反とぶら下がりポインタはどのように関連していますか?
NullPointerException
。
回答:
セグメンテーション違反は、「自分のものではない」メモリへのアクセスによって引き起こされる特定の種類のエラーです。これは、メモリの破損やデバッグが困難なメモリバグの発生を防ぐヘルパーメカニズムです。segfaultを受け取ったときはいつでも、メモリで何か問題があることを知っています。すでに解放されている変数にアクセスしたり、メモリの読み取り専用部分に書き込んだりするなどです。セグメンテーションフォールトは、ほとんどの言語で同じですメモリ管理では、CとC ++のsegfaultに主な違いはありません。
segfaultを取得する方法はたくさんありますが、少なくともC(++)などの低レベル言語ではそうです。segfaultを取得する一般的な方法は、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'
)を逆参照しようとすると、おそらくセグメンテーション違反が発生します。
c
、それがローカルであることを理解する必要があります。つまり、それは後にスタックにプッシュされ、後にスタックから{
ポップされたことを意味します}
。ダングリングポインターは、スタックから外れたオフセットへの参照にすぎません。そのため、単純なプログラムで変更しても、segfaultはトリガーされません。一方、より複雑な使用例ではsegfaultが発生する可能性があり、他の関数呼び出しがスタックを拡張して、ダングリングポインターが指すデータを含む可能性があります。そのデータへの書き込み(ローカルVARS)未定義の動作(セグメンテーション違反&Co社)につながる
SIGSEGV
ので、そのような信号がスタックを乱すことからは期待できません。
セグメンテーションフォールトは、別のプロセスメモリに直接アクセスすることによって引き起こされるのではないことに注意する価値があります(これは私が時々聞いていることです)。仮想メモリでは、すべてのプロセスに独自の仮想アドレス空間があり、ポインタの値を使用して別のプロセスにアクセスする方法はありません。これの例外は、(おそらく)異なる仮想アドレスにマップされた同じ物理アドレススペースである共有ライブラリと、すべてのプロセスで同じようにマップされたカーネルメモリです(syscallでのTLBフラッシュを回避するためだと思います)。そしてshmat;)のようなもの-これらは私が「間接的」アクセスとして数えるものです。ただし、通常はプロセスコードから遠くにあり、通常はそれらにアクセスできることを確認できます(これが理由です)
それでも、不適切な方法で(たとえば、書き込み不可能なスペースに書き込もうとするなど)自分の(プロセス)メモリにアクセスした場合、セグメンテーション違反が発生する可能性があります。しかし、その最も一般的な理由は、物理アドレス空間にまったくマッピングされていない仮想アドレス空間の部分へのアクセスです。
そして、仮想メモリシステムに関するすべてのことです。
セグメンテーション違反は、プロセスが記述子テーブルにリストしていないページに対する要求、またはリストにあるページに対する無効な要求(たとえば、読み取り専用ページでの書き込み要求)が原因で発生します。
ダングリングポインターは、有効なページを指す場合とそうでない場合がありますが、メモリーの「予期しない」セグメントを指すポインターです。
正直なところ、他のポスターが述べたように、ウィキペディアにはこれに関する非常に優れた記事があるので、そちらをご覧ください。このタイプのエラーは非常に一般的であり、アクセス違反や一般保護違反など、他のこととも呼ばれます。
C、C ++、またはポインタを許可するその他の言語でも違いはありません。これらの種類のエラーは、通常、
セグメンテーション違反は、ハードウェア障害、この場合はRAMメモリによっても引き起こされます。これはあまり一般的ではない原因ですが、コードにエラーが見つからない場合は、memtestが役立つ可能性があります。
この場合の解決策は、RAMを変更することです。
編集:
ここに参照があります:ハードウェアによるセグメンテーション違反
セグメンテーションフォールトは、プロセス(プログラムの実行中のインスタンス)が、他のプロセスで使用されている読み取り専用メモリアドレスまたはメモリ範囲にアクセスしようとしたり、存在しない(無効な)メモリアドレスにアクセスしようとしたときに発生します。 ダングリングリファレンス(ポインタ)の問題とは、メモリから既に内容が削除されているオブジェクトまたは変数にアクセスしようとすることを意味します。例:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
ウィキペディアのSegmentation_faultページには、原因と理由を指摘しただけの非常に優れた説明があります。詳細については、wikiをご覧ください。
コンピューティングでは、セグメンテーション違反(多くの場合、segfaultに短縮されます)またはアクセス違反は、メモリ保護機能を備えたハードウェアによって発生する障害であり、メモリアクセス違反についてオペレーティングシステム(OS)に通知します。
セグメンテーション違反の一般的な原因は次のとおりです。
これらは順番に、無効なメモリアクセスを引き起こすプログラミングエラーによって引き起こされることがよくあります。
初期化されていないポインタ(ランダムなメモリアドレスを指すワイルドポインタ)への逆参照または割り当て
解放されたポインタの参照解除または割り当て(解放された、割り当て解除された、または削除されたメモリを指すダングリングポインタ)
バッファオーバーフロー。
スタックオーバーフロー。
正しくコンパイルされないプログラムを実行しようとしています。(一部のコンパイラーは、コンパイル時エラーが存在しても実行可能ファイルを出力します。)
セグメンテーション違反またはアクセス違反は、プログラムが存在しないメモリ位置にアクセスしようとした場合、または許可されていない方法でメモリ位置にアクセスしようとした場合に発生します。
/* "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]が存在しないため、segfaultが発生します。
セグメンテーション違反の原因:
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).
セグメンテーション違反の十分な定義があります。プログラミング中に遭遇したいくつかの例を引用します。これはばかげた間違いに見えるかもしれませんが、多くの時間を浪費します。
printfで引数の型が一致しない場合、以下の場合にセグメンテーション違反が発生する可能性があります
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
出力: Segmentation Fault (SIGSEGV)
ポインタにメモリを割り当てるのを忘れたが、それを使用しようとしたとき。
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
出力: Segmentation Fault (SIGSEGV)
の単純な意味Segmentation fault
は、自分が所有していないメモリにアクセスしようとしていることです。Segmentation fault
読み取り専用のメモリ位置でタスクの読み取りや書き込みを行おうとしたり、メモリを解放しようとしたりすると発生します。つまり、これをある種のメモリ破損として説明できます。
以下では、プログラマーが犯した、につながる一般的な間違いについて説明しSegmentation fault
ます。
scanf()
間違った方法で使用します(置くのを忘れました&
)。int num;
scanf("%d", num);// must use &num instead of num
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
printf()
およびscanf()
' を使用する場合は、間違ったフォーマット指定子を使用してください