ATLとIUnknownPtrを使用する際にキャストするための正しい方法は何ですか?

StackOverflow https://stackoverflow.com/questions/2402333

質問

私は「方法の人々の混乱アップのIUnknown :: QueryInterfaceを」と呼ばれる「旧新シング」のブログから記事に出くわしたと開始コメント欄での議論があった既存のATL COMオブジェクトの変更時には回答者の1(ノーマンダイヤモンド)キャストがvoidへの記事の例の一つでその**が間違っていたことを。

指摘しました

しかし、私は試してみて、適切に私はメモリリークで終わる鋳造を行うには、私のコードを修正するときます。

次のように

の例は次の通りであった:

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

ノーマンは言った。

  

パンクはvoid *型ではありません。パンクは*のIUnknownです。

     

ボイドが**ユニバーサルポインタ型ではありません。 void *型ユニバーサルポインタ型である、とのchar *や親戚は、そのように等価であることがでgrandparentedされますが、無効**ではありません。

     あなたが呼び出し規約を遵守し、恐ろしい死亡を回避したい場合は、

、あなたはこれをしなければなりません。   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;

しかし、今、私のアプリケーションは、このCOMオブジェクト

からのメモリリークが発生しています
役に立ちましたか?

解決

あなたが成功すると、オブジェクトの参照カウントをインクリメントしますが、参照カウントをデクリメントし、後でGetActiveObject()を呼び出すことはありませんQueryInterface()Release()を呼び出すので、

あなたはおそらくメモリリークを持っています。

他のヒント

うーん、私はむしろパンクへのvoid *を割り当てるよりも、私は使うべきだと思います:

pUnk.Attach(reinterpret_cast<IUnknown*>(pUnkVoid));
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top