문제

기존 ATL COM 객체를 수정하는 동안 나는 "The Old New Thing"블로그에서 "The Ways Up Iunknown :: QueryInterface"라는 기사를 발견했으며 의견 섹션에서 시작된 주석 섹션에서 토론이 시작되었습니다. 응답자 (Norman Diamond)는이 기사의 예 중 하나에서 void **에 대한 캐스트가 잘못되었다고 지적했다.

그러나 코드를 제대로 수행하기 위해 코드를 수정하려고 할 때 메모리 누출로 끝납니다.

예는 다음과 같습니다.

IShellFolder *psf = some object;
IUnknown *punk = NULL;
psf->QueryInterface(IID_IUnknown, (void**)&punk);

노먼이 말했다

펑크는 무효가 아닙니다*. 펑크는 iunknown*입니다.

void **는 보편적 인 포인터 유형이 아닙니다. Void*는 보편적 인 포인터 유형이며, Char*와 친척은 그런 식으로 동등하게 조부모가되지만 Void **는 그렇지 않습니다.

부름 규칙에 순종하고 끔찍한 죽음을 피하려면 다음을 수행해야합니다. iunknown *펑크; void *punkvoid; psf-> QueryInterface (iid_iunknown, & punkvoid); 펑크 = (iunknown *) punkvoid;

다른 많은 MSDN 기고자들도 동일한 실수를 저질렀습니다 .... 어떤 사람들은 그것이 현재까지 모든 VC ++ 구현에서 작동한다고 말할 수도 있지만, 이것이 올바른 코드를 만들지는 않지만 여전히 전화 컨벤션을 위반하고 있습니다.

이것에 비추어 나는 이전 코드를 바꾸려고했다 - 이것은 다음과 같습니다.

#include <comdef.h>

...

HRESULT FinalConstruct()
{ 
    if (m_dwROTCookie != 0)
        return E_FAIL;

    //Check whether there already is an instance of the Object
    IUnknownPtr pUnk = NULL;
    if (GetActiveObject(CLSID_Object, NULL, &pUnk) == S_OK)
    {
        TRACE_WARNING("An instance of Object already exists in the current context");
        return S_OK;
    }
    HRESULT hr = QueryInterface(IID_IUnknown, reinterpret_cast<void **>(&pUnk));

    hr = RegisterActiveObject(pUnk, CLSID_Object, ACTIVEOBJECT_WEAK, m_dwROTCookie);        
    if (FAILED(hr))
        return hr;

    hr = CoLockObjectExternal(pUnk, TRUE, TRUE);
    pUnk = NULL;
    ATLASSERT(m_dwRef == 2);
    return hr;
}

그런 다음 다음과 같이 변경했습니다.

HRESULT FinalConstruct()
{ 
    if (m_dwROTCookie != 0)
        return E_FAIL;

    //Check whether there already is an instance of the Object
    IUnknownPtr pUnk = NULL;
    if (GetActiveObject(CLSID_Object, NULL, &pUnk) == S_OK)
    {
        TRACE_WARNING("An instance of Object already exists in the current context");
        return S_OK;
    }
    void* pUnkVoid = NULL;
    HRESULT hr = QueryInterface(IID_IUnknown, &pUnkVoid);

    if (SUCCEEDED(hr)
    {
        pUnk = reinterpret_cast<IUnknown*>(pUnkVoid);
        hr = RegisterActiveObject(pUnk, CLSID_Object, ACTIVEOBJECT_WEAK, m_dwROTCookie);        
        if (FAILED(hr))
            return hr;

        hr = CoLockObjectExternal(pUnk, TRUE, TRUE);
        pUnk = NULL;
    }
    ATLASSERT(m_dwRef == 2);

    return hr;

그러나 이제 내 응용 프로그램은이 제품에서 메모리 누출이 있습니다.

도움이 되었습니까?

해결책

전화하기 때문에 메모리 누출이있을 수 있습니다 GetActiveObject() 그리고 QueryInterface() 성공시 객체의 참조 계산이 증가하지만 호출하지 마십시오. Release() 나중에 참조 수를 줄이기 위해.

다른 팁

음, 나는 void*를 펑크에 할당하기보다는 다음을 사용해야한다고 생각합니다.

pUnk.Attach(reinterpret_cast<IUnknown*>(pUnkVoid));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top