2017-04-14 70 views
1

私はタイプCComPtrのオブジェクトを使用しています。しかし、私はいくつかのメモリリークの問題を抱えています。CComPtrと参照カウント

CComPtr<ID2D1Bitmap> bitmap = create_bitmap(bitmapSize); 
auto n = count_ref((ID2D1Bitmap*)bitmap); 

:私は1に等しいnの値を期待していたが、それは実際に等しい

ID2D1Bitmap* create_bitmap(const D2D1_SIZE_U& size) 
{ 
    ID2D1Bitmap* bitmap; 
    CreateBitmap(&bitmap); 

    return bitmap; 
} 

template<class Interface> 
ULONG count_ref(Interface* pInterface) noexcept 
{ 
    if (pInterface) 
    { 
     pInterface->AddRef(); 
     return pInterface->Release(); 
    } 

    return 0; 
} 

特に、私は次のコードを持っています2.私のCComPtrの参照カウントが1でないのはなぜですか?

私のCComPtrオブジェクトを正しく使用していますか?

とするとき、プロセスは、私は、次のメモリリークを取得終了:

An interface [072B1F50] was created but not released. Use 'dps 072B1F20' to view its allocation stack. 
Object type: ID2D1Bitmap 
    Device-dependent size: 1000 x 600 
    Device-independent size: 1000.00 x 600.00 
    Format: DXGI_FORMAT_B8G8R8A8_UNORM 
    Alpha mode: D2D1_ALPHA_MODE_PREMULTIPLIED 
    Outstanding reference count: 1 

D2D DEBUG ERROR - Memory leaks detected. 
+0

インターフェイスポインタの所有権をCComPtr :: Attach()で取得します。 –

答えて

3

CComPtrでは、生のインターフェイスのポインタタイプを使う必要はほとんどありません。あなたはこのようにそれを行うことができます

、例えば:ローカル変数、戻り値、新しいローカル値:

CComPtr<ID2D1Bitmap> create_bitmap(const D2D1_SIZE_U& size) 
{ 
    CComPtr<ID2D1Bitmap> bitmap; 
    CreateBitmap(&bitmap); // Declared as CreateBitmap(ID2D1Bitmap**); 
    return bitmap; 
} 

CComPtr<ID2D1Bitmap> pBitmap = create_bitmap(...); 
... 

CComPtrクラスを使用すると、ポインタを渡す方法に沿って正確に参照を管理します。リリースビルドでコンパイラを最適化すると、余分なAddRef /リリースの一部も削除されるので、あまり心配する必要はありません。

2

あなたは、ポインタからCComPtrを構築する場合、それはこのポインタの所有権を共有し、参照カウントをインクリメントしますが。参照カウントをインクリメントせずにポインタの所有権を取得するには、CComPtr::Attach methodを使用します。

CComPtr<ID2D1Bitmap> bitmap; 
bitmap.Attach(create_bitmap(bitmapSize)); 
1

このコードにはいくつかの問題があります。

問題は軽微ですが、誤解を招く可能性があります。 AddRef()およびRelease()は、not actually required to return any sensible valuesである。だから、彼らは実際の参照カウントを返すのは良いですが、毎回これに頼ることはできません。だから基本的にあなたのcount_ref()関数は素朴で信頼性がありません。

Release()が実際の参照カウントを返したとすると、create_bitmap()はすでに参照カウントが1に設定されているオブジェクトを返します。次にCComPtrAddRef()を呼び出し、参照カウントは2に変わります。そして、CComPtrが有効範囲外になると、デストラクタはRelease()を呼び出し、オブジェクトへのポインタがなくなり、それがリークします。

後で問題を解決するには、単にもう一度呼ばれるAddRef()を持たずにcreate_bitmap()によって返されるオブジェクトの所有権を取得するためにCComPtr::Attach()を使用することです:コードの作業になるだろう

CComPtr<ID2D1Bitmap> bitmap; 
bitmap.Attach(create_bitmap(bitmapSize)); 

が、それは非常に明確ではないですし、必要以上に維持するのが少し難しいかもしれません。 create_bitmap()シグネチャを変更する余裕がある場合は、CComPtrthe other answerとして返すように変更する方がよいでしょう。これは、発信者がオブジェクトの所有権をファンクションシグネチャを見ている人に持っていなければならず、Attach()への別の呼び出しを使う必要がないことを明示しています。

関連する問題