8

逆参照された「オブジェクト」に実際にアクセスしない場合、null ポインターの逆参照はまだ未定義ですか?

int* p = 0;
int& r = *p;    // undefined?
int* q = &*p;   // undefined?

もう少し実用的な例: null ポインターを逆参照して、オーバーロードを区別できますか?

void foo(Bar&);
void foo(Baz&);

foo(*(Bar*)0);  // undefined?

さて、参照例は、標準に従って間違いなく未定義の動作です。

そのような参照を作成する唯一の方法は、未定義の動作を引き起こすnull ポインターを逆参照することによって取得された「オブジェクト」にバインドすることであるため、null 参照は明確に定義されたプログラムには存在できません。

残念ながら、強調された部分はあいまいです。未定義の動作を引き起こすのはバインディング部分ですか、それとも逆参照部分で十分ですか?

4

3 に答える 3

6

すべての C プログラマーが未定義の動作について知っておくべきことの 2 番目の作品は、この問題を説明するのに役立つと思います。

ブログを例にとると:

void contains_null_check(int *P) {
  int dead = *P;
  if (P == 0)
    return;
  *P = 4;
}

(RNCE: Redundant Null Check Elimintation) に最適化される可能性があります:

void contains_null_check_after_RNCE(int *P) {
  int dead = *P;
  if (false)  // P was dereferenced by this point, so it can't be null 
    return;
  *P = 4;
}

これは次のように最適化されます (DCE: Dead Code Elimination):

void contains_null_check_after_RNCE_and_DCE(int *P) {
  //int dead = *P; -- dead store
  //if (false)     -- unreachable branch
  //  return;
  *P = 4;
}

ご覧のとおり、 は使用されていdeadませが、単純なint dead = *P代入により、未定義の動作がプログラムに忍び寄っています。

オーバーロードを区別するには、人為的に null 参照を作成して未定義の動作にさらすのではなく、ポインター (null の可能性があります) を使用することをお勧めします。

于 2011-08-20T10:58:17.747 に答える
5
int& r = *p;    // undefined?

ここでは、逆参照されたオブジェクト(または) を実際に使用していなくても、未定義の動作があると思います。このステップ (つまり、ヌル ポインターの逆参照) の後、プログラムの動作は言語によって保証されないためです。これは、UB の可能性の 1 つであるプログラムがすぐにクラッシュする可能性があるためです。真の目的で使用するためにの値を読み取るだけでUB を呼び出すと考えているようです。私はそうは思わない。r*pr

また、言語仕様では、「ヌル ポインターの逆参照の効果」が未定義の動作を引き起こすと明確に述べられています。「実際にnull ポインターから逆参照されたオブジェクトを使用する効果」が UB を呼び出すとは言いません。ヌル ポインターの逆参照の影響 (つまり、未定義の動作) は、必ずしもすぐに問題が発生したり、ヌル ポインターの逆参照の直後にクラッシュしたりすることを意味するわけではありません。いいえ。これは単に、null ポインターを逆参照したにプログラムの動作が定義されていないことを意味します。つまり、プログラム期待どおり、最初から最後まで正常に実行されます。または、すぐにクラッシュすることもあれば、数分後、数時間後、または数日後にクラッシュすることもあります。null ポインターを逆参照した後は、いつでも 何かが発生する可能性があります。

于 2011-08-20T09:36:31.730 に答える
4

はい、未定義の動作です。仕様では、「左辺値はオブジェクトまたは関数を指定する」(節 3.10) と述べられており、*-operator については「[逆参照の]結果は、オブジェクトまたは関数を参照する左辺値である」と述べられているためです。表現ポイント」(5.3.1節)。

つまり、null ポインターを逆参照したときに何が起こるかについての説明はありません。それは単に未定義の動作です。

于 2011-08-20T15:01:09.863 に答える