私は完全に壊れているように見えるこのコードに出くわしましたが、それは実際に起こりthis
ますnull
。これがどうなるかわからないnull
これは、次のような通常のメソッド呼び出しの内部にあります。
myObject->func();
中MyObject::func()
には
if (!this) { return false; }
(?)メソッドNullPointerException
の中に入る代わりに最初の行をスローする方法はありますか?null
あなたが持っている場合:
MyObject *o = NULL;
o->func();
次に何が起こるかfunc
は、仮想かどうかによって異なります。そうである場合、vtable を取得するオブジェクトが必要なため、クラッシュします。ただし、仮想でない場合、呼び出しは this ポインターを NULL に設定して続行します。
標準ではこれは「未定義の動作」であると述べているため、何かが起こる可能性がありますが、通常のコンパイラは、ポインターが NULL かどうかをチェックしないようにコードを生成するだけです。いくつかのよく知られているライブラリは、私が説明した動作に依存しています。MFC にはSafeGetHandle
、null ポインターで呼び出すことができるような関数があり、その場合は NULL を返します。
再利用可能なヘルパー関数を書きたいと思うかもしれません:
void CheckNotNull(void *p)
{
if (p == NULL)
throw NullPointerException();
}
次に、関数の開始時にそれを使用して、以下を含むすべての引数をチェックできますthis
。
CheckNotNull(this);
shared_ptr
これらの種類のエラーを (設計により) トラップする方法は、null ポインター引数を使用して作成時にスローするポインター ラッパー クラス (に似ている) を使用することです。逆参照されたときにもスローされる可能性がありますが、それは少し遅いです-何もないよりはましだと思います。
if(this == null)
throw new NullPointerException;
if(!this)
return false;
this
null になる可能性があります。このコードは、オブジェクトの初期化がまだ完了していない、または削除された競合状態を (ひどく) 検出しようとしていると思われます。
(this == NULL) は、標準によれば未定義の動作です。このチェックを削除する必要があると思います:)
次の呼び出しを行うとします。
((CSomeClass*) 0)->method();
動作はすでに定義されていないので、わざわざ CSomeClass::method で == NULL のチェックを行う必要はありません。
編集済み: メンバー変数を使用しない場合、コンパイラは (0 == this) を処理すると仮定しますが、仮想テーブル ポインタはどこにあるのでしょうか? この場合、あなたのクラスはポリモーフィズムを使用できません。
このポインターは、次のような場合に null になる可能性があります。
class Test
{
public:
bool f();
private:
int m_i;
};
bool Test::f()
{
if(!this)
{
return false;
}
m_i = 0;
return true;
}
int main(int argc, char **argv)
{
Test* p = new Test;
delete p;
p = NULL;
p->f();
}
アクセス違反の例外を回避するために、誰かが簡単なハックをしたと思います。
this == null は、削除されたオブジェクトでメソッドを呼び出している場合、または何かがメモリに書き込まれてはならない (特にオブジェクトの this ポインターを上書きしている) 場合にのみ発生します。
このように回避しようとするのではなく、コードの実際の問題を調査する必要があります。