在我读到一篇文章,来自名为“方式让人们陷入困境的IUnknown ::的QueryInterface”的“旧的新”的博客,并有一个在评论部分,当开始讨论现有的ATL COM对象的修改的受访者(诺曼钻石)指出,在所述的制品的例子之一,所述铸造为void **是不正确的。

然而,当我试图纠正我的代码做铸造正确我结束了内存泄漏。

的例子如下:

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

诺曼说

  

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

     

无效**不是通用指针类型。 void *的是一种通用的指针类型和char *和亲戚grandparented中要以这种方式相当,但无效**不是。

     

如果您要服从调用约定,避免可怕的死亡,你必须这样做:   *的IUnknown朋克;   无效* 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;

但是现在我的应用程序具有从该内存泄漏的COM对象

有帮助吗?

解决方案

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

其他提示

嗯,我认为,而不是分配无效*朋克我应该使用:

pUnk.Attach(reinterpret_cast<IUnknown*>(pUnkVoid));
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top