2017-04-14 23 views
1

CComPtr 유형의 개체를 사용하고 있습니다. 하지만 메모리 누수 문제가 있습니다.CComPtr 및 참조 카운트

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

:

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

    return 0; 
} 

그리고 : 특히, 나는 다음과 같은 코드가

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

    return bitmap; 
} 

내가 1과 동일한 n의 값을 기다리고 있었다를하지만, 실제로 동일 2. 내 CComPtr의 참조 횟수가 1이 아닌 이유는 무엇입니까?

CComPtr 개체를 올바르게 사용하고 있습니까?

그리고 프로세스가 나는 다음과 같은 메모리 누수 얻을 종료 될 때 : 당신이 포인터에서 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<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/Releases도 일부 제거되므로 그다지 걱정할 필요가 없습니다.

2

하는 것이이 포인터와 증가 참조 횟수의 소유권을 공유됩니다. 참조 카운트를 증가시키지 않고 포인터의 소유권을 얻으려면 CComPtr::Attach method을 사용하십시오. CComPtr

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() 서명을 변경할 수 있다면 the other answer에 제안 된대로 CComPtr을 반환하도록 변경하는 것이 좋습니다.따라서 호출자는 함수 서명을 보는 사람에게 객체의 소유권을 가져야하고 Attach()에 대한 별도의 호출을 사용할 필요가 없음을 분명히 알 수 있습니다.