14

ポインターを使用してデータブロックにアクセスするコードがあります。まれに、データブロックのいくつかのメンバーが空であり、その結果、ポインターがぶら下がります。実際、正しいポインターを取得できますが、ポインターで何かをしようとするとプログラムがクラッシュします。

通常のアドバイスは、このタイプの使用を避けることです。しかし悲しいことに、私が使用しているフレームワークでは、このタイプのデータ アクセス方法を使用する必要があります。

ポインターを操作する前に、ポインターが無効かどうかを「確認」する方法はありますか? ポインターが NULL と等しくないことを確認しても、明らかに機能しませんでした。私もこれを試しました:

try
{
    CString csClassName = typeid(*pMyPointer).name();  // Check error condition
    // The line below fails due to dangling pointer (data block is not valid).
    hr = pMyPointer->MyPointerMethod(); 
}
catch(bad_typeid)
{
    return E_FAIL;
}
catch(...)
{
    return E_FAIL;
}

それは正しい方法ですか?

4

4 に答える 4

9

生のポインターが有効かどうかを確認する方法はありません。無効なポインターは、アクセス時に失敗する保証はありません。生のポインターを使用する代わりに、何らかの形式のスマート ポインターを使用する必要があります。

于 2011-10-05T09:25:57.470 に答える
7

あなたは間違った方向を見ていると思います。おそらく、ポインターを正しく初期化していない、オブジェクトを削除するのが早すぎる、削除された後にポインターを再利用しようとするなどのバグがあるでしょう。その場合は、バグを隠す方法を探すのではなく、なぜそれが起こっているのかを突き止めてバグを修正することに集中する必要があります。

オペレーターで使用しているアプローチの時点でtypeid、答えは有効ではないということです。仮想関数を含まない型のオブジェクトの場合、typeid演算子はポインターの静的型に基づいてコンパイル時に解決されます。少なくとも 1 つの仮想関数を含むオブジェクトの場合、実行時に解決されますがtypeid(p)、無効なポインターを使用した呼び出しは未定義の動作であり、動作しているように見えるのと同じようにクラッシュする可能性があります。

提案されているスマート ポインターの使用は、ライブラリが実際に行うことと、常にスマート ポインターを渡すことができるかどうかによって異なります。delete一般に、メモリ管理にスマート ポインターを使用することをお勧めします。これにより、ポインターが正しく初期化されることが保証されます (問題が初期化である場合は修正します)。手動で行う必要がなくなったため、問題が早期削除により、それはもはや起こりません。ただし、これで問題が解決する可能性がありますが、アプリケーションでポインターが無効である理由を理解する必要があることに注意してください。これは、より大きな問題の兆候である可能性があるためです。

さて、ポインターがぶら下がっているかどうかをチェックする方法の元の質問については、プログラムでそれを行うことはできませんが、メモリデバッガー (Linux の valgrind、Purify、または Linux の他のセット) 内でプログラムを実行できます。このツールは、ポインターが初期化されていないかどうか、または誤った使用の前にシステムにメモリを解放したかどうかを判断するのに役立ちます。

于 2011-10-05T10:14:53.607 に答える
3

はい、スマート ポインターを使用できます。

于 2011-10-05T09:26:20.620 に答える