0

Visual C++ 2010 では、次のスニペットが疑わしい動作を隠しています。

CObject* myObjectPtr = CObjectFactory::MakeAnObject();
assert( myObjectPtr->CanDoSomeWork() ); // myObjectPtr can be null due to logical errors

次のスニペットを関数に配置すると、ポインターが NULL で関数がすぐに返されたときにアサートがトリガーされませんでした。追加のヌル ポインター チェックの明らかな修正を別として、誰でも提案できることですが、コードがそのような動作をした原因は何ですか? アサート内でエラーが発生したとしても、通常はメモリアクセス違反エラーについて文句を言うべきではありませんか?

4

2 に答える 2

2
myObjectPtr->CanDoSomeWork()

CanDoSomeWork が仮想関数でない場合、コンパイラは事実上これを C_Object::CanDoSomeWork(myObjectPtr) として書き換えます。

これには、オブジェクト ポインターの逆参照はまったく含まれないため、クラッシュしたり失敗したりすることはありません。仮想関数の場合、ポインターを使用して vtable を見つけるため、クラッシュする可能性があります。

もちろん、これは標準で保証されているものではなく、すべて未定義の動作ですが、何が起こっているのかを説明しています。

于 2013-04-25T10:53:32.410 に答える
1
assert( myObjectPtr->CanDoSomeWork() );

NULL の場合、segfault (または UB)myObjectPtrが発生します。NULL->* は未定義の動作であるためです。最初に NULL ポインターでない
かどうかを確認する必要があります。myObjectPtr

assert (myObjectPtr != 0);
assert( myObjectPtr->CanDoSomeWork() .....);  // if you still need this (?)
于 2013-04-25T08:58:36.503 に答える