Under what conditions is CCmdTarget::OnFinalRelease called?

前端 未结 2 1805
陌清茗
陌清茗 2021-01-23 01:20

The MSDN documentation for the CCmdTarget::OnFinalRelease method is pretty brief:

Called by the framework when the last OLE reference to or from the obj

相关标签:
2条回答
  • 2021-01-23 01:33

    It doesn't appear that you ever call myEventHandler->Release(). Therefore, the last reference is never released, and OnFinalRelease is never called.

    0 讨论(0)
  • 2021-01-23 01:46

    With COM you should always use the CoCreateInstance() AddRef() and Release() paradigm to manage lifetime of your objects, and let COM do the destruction of your objects based on reference counts. Avoid new and delete because using them breaks this paradigm and causes interesting side effects. You probably have a bug in the management of the reference counts.

    The way to debug why the reference counts are not being managed correctly is to override CCmdTarget::InternalRelease() copy the source from oleunk.cpp and put some trace output or break points.

    DWORD CMyEventHandler::InternalRelease()
    {
        ASSERT(GetInterfaceMap() != NULL);
    
        if (m_dwRef == 0)
            return 0;
    
        LONG lResult = InterlockedDecrement(&m_dwRef);
        if (lResult == 0)
        {
            AFX_MANAGE_STATE(m_pModuleState);
            OnFinalRelease();
        }
        return lResult;
    }
    

    There are lots of times when passing IDispatch interfaces that code will bump reference counts and you have to decrement the reference count using Release(). Pay attention to where your code may be passing this interface because there is aconvention in COM that when Interfaces are passed using [in] or [out] where the caller or callee has to release the interface.

    When the reference count issue is corrected you shoudl see the objects OnFinalRelease code being called and the object destoryed by hte MFC framework:

    For CCmdTarget the destruction should happen as a result of the final release in the parent class CWnd:

    void CWnd::OnFinalRelease()
    {
        if (m_hWnd != NULL)
            DestroyWindow();    // will call PostNcDestroy
        else
            PostNcDestroy();
    }
    

    FYI: Passing interfaces across threads without marshalling the interface pointers is another common reason to get errors in COM.

    0 讨论(0)
提交回复
热议问题