2016-04-25 37 views
-1

私はこのようなクラスまたは構造体を持っている場合: DirectX COMオブジェクトでこのような状況でメモリリークが発生しましたか?

この関数何か中の任意の時点で失敗し、それが最後でクリーンアップを行いません、falseを返す場合

bool localScopeFunc() 
 
{ 
 
    bool result; 
 
    IDXGIFactory* pFactory; 
 
    IDXGIAdapter* pAdapter; 
 
    
 
    result = //Do something here with the objects 
 
\t if (!result) return false; 
 
    
 
\t result = //Do something here with the objects 
 
\t if (!result) return false; 
 
    
 
\t result = //Do something here with the objects 
 
\t if (!result) return false; 
 
    // And so on...... 
 
    
 
    
 
    //___Do cleanup here___// 
 
    pFactory->Release(); pFactory = nullptr; 
 
    pAdapter->Release(); pAdapter = nullptr; 
 
    
 
    return true; // If all passes 
 
}
、したがって、任意のオブジェクトに対して - > Release()を呼び出すことはありません。これはメモリリークを意味しますか?

もしそうなら、実現可能な方法を見つけることができません。時々私は関数呼び出しのリストを持っていて、新しい段階を初期化する各段階で、逆にすべてをクリーンアップしなければならない

int main() 
 
{ 
 
if (!initTime()) {return -1;} 
 
if (!initD3D())  {shutDownTime(); return -2;} 
 
if (!initCamera()) {shutDownD3D(); shutDownTime(); return -3;} 
 
if (!initSound()) {shutDownCamera(); shutDownD3D(); shutDownTime(); return -3;} 
 
if (!initPhysics()) {shutDownSound(); shutDownD3D(); shutDownTime(); return -4;} 
 
// And so on. 
 
    
 
return 0; 
 
}

答えて

1

あなたはクリーンアップをスキップしているので、はい、それはリークが発生します:次のようになります。 COMオブジェクトは参照カウントを使用し、適切な時間にメモリを削除するためには、カウントが正確でなければなりません。

解決策は実際には非常に簡単です:Microsoft::WRL::ComPtrを使用してください。このスマートポインタは、スコープから離れる場合でも必要に応じてReleaseを呼び出す処理を行います。

その他の注意点は、COMオブジェクトはboolとしてエラーを返さないことです。彼らはHRESULTです。関数がHRESULTを返すと失敗する可能性があるので、無視しないでください。また、== S_OKなどを使うべきではありません。 FAILEDマクロ、SUCCEEDEDマクロ、またはDX::ThrowIfFailedなどのマクロを使用する必要があります。

#include <wrl/client.h> 

using Microsoft::WRL::ComPtr; 

bool localScopeFunc() 
{ 
    ComPtr<IDXGIFactory> pFactory; 
    ComPtr<IDXGIAdapter> pAdapter; 

    HRESULT result = //Do something here with the objects 
    if (FAILED(result)) return false; 

    result = //Do something here with the objects 
    if (FAILED(result)) return false; 

    result = //Do something here with the objects 
    if (FAILED(result)) return false; 

    // And so on...... 

    return true; // If all passes 
} 

ComPtrの詳細については、thisを参照してください。

+0

ありがとうチャック。私はこれまでのところ未処理のポインタしか使用していませんでしたが、ComPtrとunique_pointerはこのようなことに非常に便利です。 ComPtrは、unique_pointerまたはshared_pointerとのより多くの類似点を共有しますか? また、私は2つのCOMオブジェクトメソッド.get()と.getAddressOf()の違いを見つけようとしています。 MSDNからは、言葉の表現が同等であると私は理解できません。 .get()またはgetAddressOf()を引数として渡す必要がありますか?ありがとう。 – Zebrafish

+0

'' ComPtr''は参照カウント共有スマートポインタなので、 '' shared_ptr''と論理的に似ています。 '' ComPtr''の使用方法のヒントについては、[this](https://github.com/Microsoft/DirectXTK/wiki/ComPtr)を参照してください。ここでは、 '' Get''と '' GetAddressOf '' Direct3Dのパラメータで使用されます。 –

+0

ありがとう、私は約3回それを読んだ。違いはget()はポインタで、getAddressOf()はポインタのアドレスで、ポインタ引数へのポインタを取る関数に渡すことができます。 あなたが説明してもらえればもう1つのこと。通常、何かへのポインタを作成した場合は、直後にnullかどうかを確認することができます。これは、失敗を示すものです。だから私が行くとき(!ptr)falseを返します。 、if(!ptr.get())がfalseを返すように変更する必要があります。 ?ユニークなptrはポインタ自体ではなく、1つのラッパーです。 – Zebrafish

関連する問題