C および C++ でのセグメンテーション違反

この記事では、C および C++ でのセグメンテーション違反の考えと、C および C++ でのセグメンテーション違反の考えられるさまざまな理由について説明しました。

目次 :

<オール>
  • セグメンテーション フォールトの概要
  • C と C++ で異なるセグメンテーション違反
  • セグメンテーション フォールトの概要

    C と C++ のセグメンテーション違反に大きな違いはありません。
    まず、「セグメンテーション フォールト」 とは何かを理解しましょう

    セグメンテーション違反は、「アクセス違反」とも呼ばれます 要するに segfault .これは、メモリ保護を備えたハードウェアが原因で発生した障害状態であり、ソフトウェアがメモリの制限された領域にアクセスしようとしていることが OS に通知されます。これらは、低レベルのメモリ アクセスを提供する C や C++ などのプログラミング言語で見られる、仮想メモリ アドレッシング用のポインタの使用エラーによるものです。Java などの他のプログラミング言語では と Lisp ガベージ コレクションを使用して、セグメンテーション フォールトを回避する特定のクラスのエラーを回避します。

    C と C++ で異なるセグメンテーション エラー

    以下は、C および C++ でのセグメンテーション違反の背後にあるさまざまな理由です:

    • メモリの読み取り専用部分に書き込もうとしています
    • 範囲外の配列へのアクセス
    • 変数値をアドレスとして使用
    • NULL ポインタの逆参照
    • 初期化されていないポインタへの逆参照または代入
    • 解放されたポインタへの逆参照または代入
    • バッファ オーバーフロー
    • スタック オーバーフロー

    <私>

    では、セグメンテーション違反の原因を見てみましょう

    いくつかの異なる理由が考えられます:

    • メモリの読み取り専用部分に書き込もうとしています

    以下のコード スニペットを調べてください

    // Writing in read only portion
    #include<stdio.h>
    int main()
    {
        char *str="a";   //pointer considered as read-only 
        *str="b";       //Cannot write here
        printf("%c",*str); // try to print the value
    }
    

    エラー:

    assignment to ‘char’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion]
    
    Error in line :
        5 |     *str="b";       //Cannot write here
    

    "*str" を印刷してみることができます 上記のコード スニペットに printf を使用すると、エラーが発生します。後で、2 行目をコメント化して試すことができます。例:*str="b" エラーがデバッグされているため、出力を確実に取得できます。つまり、読み取り専用部分に書き込むことはもうありません。

    • 範囲外の配列にアクセスしています
    // Accessing greater than upper limit
    #include<stdio.h>
    int main()
    {
      int arr[5],i;
      for(i=0;i<=6;i++)
         {
            arr[i]=i;    //error at arr[5] and arr[6] as index ranges between 0 to 4
         }  
    }
    

    エラー:

    *** stack smashing detected ***: terminated
    
    • 変数値をアドレスとして使用
    // Usage of & with variable
    #include<stdio.h>
    int main()
    {
      int num=0;
      scanf("%d",num);    //variable should be passed with & here
    }
    

    エラー:

    format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
    
    Error at line:
       5 |   scanf("%d",num); 
    

    ここでは、入力を取得するために変数のアドレスを渡す必要があります。つまり、&num です。 変数の値を渡すと、セグメンテーション違反が発生するためです。

    • NULL ポインタの逆参照
    #include<stdio.h>
    int main()
    {
      int *ptr=NULL;
      *ptr=1;          // causing segmenation fault
      printf("%d",*ptr);
    }
    

    エラー:

    Error: Here,we can't see any error or any warnings but there will be no output for the code
    

    NULL 通常、ポインターは、プロセスのアドレス空間の一部ではないアドレスを指します。したがって、Null ポインターを逆参照すると、segfault が発生します。

    • 初期化されていないポインタへの逆参照または代入
    #include<stdio.h>
    int main()
    {
      int *ptr;         //wild pointer
      *ptr=1;          // causing segmenation fault
      printf("%d",*ptr);
    }
    

    エラー:

    Error: Here,we can't see any error or any warnings but there will be no output for the code
    

    ワイルド 通常、ポインターは、プロセスのアドレス空間の一部である場合とそうでない場合があるランダムなメモリ アドレスを指します。したがって、ワイルド ポインターに逆参照または値を代入すると、segfault が発生します。

    • 解放されたポインタへの逆参照または代入
    #include<stdio.h>
    #inlude<stdlib.h>
    int main()
    {
      int *ptr = malloc(sizeof(int)*10); //dangling pointer
      free(ptr);
      *ptr=1;          // causing segmenation fault
      printf("%d",*ptr);
    }
    

    • バッファ オーバーフロー
    #include<stdio.h>
    int main()
    {
      char s[3]="hello;
      printf("%s",s);
    }
    

    出力:

    hel
    
    warning:[Warning] initializer-string for array of chars is too long
    

    メモリ 隣接メモリ
    "ヘル" "lo\0"

    ここで、char 配列 s は 3 文字のみを保持することになっていました。したがって、s[3] に割り当てられた値は 3 文字のみを格納することになっていましたが、「hello」という単語は 5 文字で構成され、隣接するメモリ アドレスで上書きされ、segfault が発生します。

    • スタック オーバーフロー
    int see()
    {
    return see();
    }
    

    ここで、see() は、セグメンテーション違反につながる再帰関数自体を無限に呼び出します。

    OpenGenus のこの記事を読めば、C および C++ におけるセグメンテーション違反の完全なアイデアが得られるはずです。