15

以下のようなCプログラムを書きました。

ケース1

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

*a=11;

a=&b;/* store address of b in pointer variable*/

プログラムを実行すると、セグメンテーション違反が発生します。

次のようにコードを変更しました。

ケース 2

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

a=&b;/* store address of b in pointer variable*/

*a=11;

今では正常に動作しています。

誰かが知っている場合は、CASE 1 でセグメンテーション違反が発生する理由を説明してください。

4

5 に答える 5

23
CASE .1

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

*a=11;//Not valid means you are not owner of the address where a now pointing it is unknown and accessing this will segfault/

a=&b;/* store address of b in pointer variable*/

使用しているアドレスが有効なアドレスではなく、不正な 11 を保存しているため、これはセグメンテーション違反になります。

                               b
      +-------+            +--------+
      |       +            |   11   |
      |Unknown|            |        |
      +---+---+            +---+----+
          |                    |
          |                    |
          +                    +
          a                    a
CASE .2

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

a=&b;/* store address of b in pointer variable*/

*a=11;

b のアドレスが有効であり、合法である 11 を保存しているため、現在は正常に機能しています。

また、上記のケースはポインター宣言の正しい方法ではありません

  int *a  = NUll;
  a = malloc(sizeof(int));
  *a=5;
  free(a);//must

また

 int *a  = NUll;
 int b;
 a = &b;
 *a=5;

これにより、見つけにくいセグメンテーション違反が何度も解消されます。

于 2013-07-26T05:46:37.837 に答える
4

1 行: 未定義の動作を示す初期化されていないポインターを逆参照している最初のコードと、アドレスの値にアクセスできる初期化されたポインターを逆参照している 2 番目のコード。

少し説明:

最初に、ポインターは整数に過ぎないことを認識する必要があります。これ*varにより、変数の内容var(その中の整数) をアドレスとして使用して、そのアドレスの値をフェッチすることをコンパイラーに伝えます。同様に、変数の格納された値を使用してアドレスの値をフェッチし、このフェッチされた値をアドレスとして使用して、そこに格納されている値をフェッチする**varことをコンパイラに伝えます。var

したがって、最初の宣言では次のようになります。

           +----------+        +----------+
           |  garbage |        |  garbage |
           +----------+        +----------+
           |    a     |        |    b     |
           +----------+        +----------+
           |  addr1   |        |  addr2   |
           +----------+        +----------+

次に、に格納されている値をアドレスとして使用しようとしaます。aガベージが含まれている場合、任意の値にすることができますが、どのアドレスの場所にもアクセスできません。したがって、次の瞬間に*a、保存されaた値がアドレスとして使用されます。格納される値は何でもよいため、何でも起こり得ます。

location にアクセスする権限がある場合、コードはセグメンテーション エラーなしで実行され続けます。アドレスがたまたまヒープ簿記構造、またはコードがヒープまたはスタックから割り当てた他のメモリ領域からのアドレスである場合、そのアドレス*a = 10の既存の値を単純に消去10します。これは、コンテキストがメモリの実際の権限を持っていることを知らずに何かを変更したため、未定義の動作につながる可能性があります。メモリへのアクセス許可がない場合は、単純にセグメンテーション エラーが発生します。これは、初期化されていないポインターの逆参照と呼ばれます。

次のステートメントは、 ina = &bのアドレスを割り当てるだけです。前の行が初期化されていないポインターを逆参照しているため、これは役に立ちません。ba

次のコードでは、3 番目のステートメントの後に次のようなものがあります。

           +----------+        +----------+
           |  addr2   |---+    |  garbage |
           +----------+   |    +----------+
           |    a     |   +--> |    b     |
           +----------+        +----------+
           |  addr1   |        |  addr2   |
           +----------+        +----------+

b3 番目のステートメントは、 のアドレスをinto に割り当てますa。before thataは逆参照されないため、初期化前に格納されたガベージ値aがアドレスとして使用されることはありません。知識の有効なアドレスを に割り当てるとa、逆参照aにより、 が指す値にアクセスできるようになりますa

答えを拡張すると、ポインターに有効なアドレスを割り当てた場合でも、ポインターを逆参照するときに、ポインターが指すアドレスの有効期限が切れていないことを確認する必要があることに注意する必要があります。たとえば、ローカル変数を返します。

int foo (void)
{
  int a = 50;
  return &a;  //Address is valid
}//After this `a' is destroyed (lifetime finishes), accessing this address
 //results in undefined behaviour

int main (void)
{
  int *v = foo ();
  *v = 50; //Incorrect, contents of `v' has expired lifetime.
  return 0;
}

ヒープから解放されたメモリ位置にアクセスする場合も同様です。

int main (void)
{
  char *a = malloc (1);
  *a = 'A'; //Works fine, because we have allocated memory
  free (a); //Freeing allocated memory
  *a = 'B'; //Undefined behaviour, we have already freed 
            //memory, it's not for us now.
  return 0;
}
于 2013-07-26T06:05:32.473 に答える
2

最初のケースでは、ポインターを宣言しましたが、ポインターが指す必要があるアドレスを割り当てていないため、ポインターにはシステム内の別のプロセスに属するアドレスが含まれていました (または、ジャンク値が含まれていた可能性があります)。はまったくアドレスではないか、メモリ アドレスにできない null が含まれている可能性があるため、オペレーティング システムは無効なメモリ操作を防止するために信号を送信し、セグメンテーション フォールトが発生します。

2番目のケースでは、更新する必要がある変数のアドレスをポインターに割り当て、値を保存するのが正しい方法であるため、セグメンテーション違反はありません。

于 2013-07-26T05:42:23.993 に答える
1

int a はランダムな整数値を格納します。つまり、*a と言って、範囲外または無効なメモリ位置にアクセスしている可能性があります。というわけでセグフォルトです。

于 2013-07-26T05:28:10.367 に答える