2010-03-08 116 views
0

在修改现有ATL COM对象的过程中,我遇到了一篇名为“人们弄乱了IUnknown :: QueryInterface的方式”的“The Old New Thing”博客文章,并且在评论部分有一个讨论,的受访者(诺曼钻石)指出,在文章的一个例子中,抛弃**是错误的。使用ATL和IUnknownPtr时,正确的方法是什么?

但是,当我尝试纠正我的代码来正确执行投射时,我最终发生内存泄漏。

的例子如下:

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

诺曼说

朋克不是一个void *。朋克是一个IUnknown *。

void **不是通用指针类型。 void *是一个通用的指针类型,并且char *和亲属是以类似的方式上传的,但void **不是。

如果你想服从调用约定并避免可怕的死亡,你必须这样做: IUnknown * punk; void * punkvoid; psf-> QueryInterface(IID_IUnknown,& punkvoid); punk =(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; 

但是现在我的应用程序有一个内存泄漏从这个COM对象

回答

0

你可能有内存泄漏,因为你叫GetActiveObject()QueryInterface()其在成功递增对象的引用计数,但不叫Release()以后递减引用计数。

0

嗯,我认为,而不是分配void * pUnk我应该使用:

pUnk.Attach(reinterpret_cast<IUnknown*>(pUnkVoid)); 
相关问题