【发布时间】:2011-10-13 18:39:15
【问题描述】:
我正在遵循为"How to create a sink interface in a MFC-based COM client" 提供的 Microsoft 示例代码,以便在 C++ (VC6) 中创建事件接收器。事件源是一个 .NET 程序集,它通过 COM 互操作公开其功能。
让我很满意的是样本的最后一个音符:
由于 CMySink 是在堆上创建的,请确保将其删除到 避免内存泄漏。
我注意到几点:
- GetIDispatch 和 AfxConnectAdvise / AfxConnectUnadvise 的自动递增/递减参数设置为 FALSE,因此我假设接收器的内部引用计数在整个练习过程中保持不变。
- 练习中没有显示 OnFinalRelease 方法,所以我假设它是删除接收器实例的默认行为。
请记住示例文本中的最后一点,我的清理代码如下所示:
//Get a pointer to sinks IUnknown, no AddRef.
LPUNKNOWN pUnkSink = m_pSink->GetIDispatch(FALSE);
//Terminate a connection between source and sink.
//m_pUnkSrc is IUnknown of server obtained by CoCreateInstance().
//m_dwCookie is a value obtained through AfxConnectionAdvise().
AfxConnectionUnadvise(m_pUnkSrc, IID_MYEVENT, pUnkSink, FALSE,
m_dwCookie);
delete m_pUnkSink;
此示例的代码是在一个循环中运行的一部分,该循环涉及创建接收器、连接它、等待一些事件,然后将其拆除并删除它。我看到的是,在循环几轮之后,突然调用 OnFinalRelease。不仅如此,还在当前循环迭代的接收器实例上调用 OnFinalRelease(不是循环的先前迭代使用的某个先前实例)。效果是当前sink在当前循环执行下被删除了,导致一堆空指针错误。
我尝试删除删除 m_pUnkSink 的调用。结果是永远不会调用 OnFinalRelease。这给我留下了内存泄漏,因为所有这些接收器实例都在堆中累积。
我想我可能会为循环的每次迭代重复使用相同的接收器实例,但我很好奇正确的生命周期管理是什么。我是否需要在自己删除实例和覆盖 OnFinalRelease 以不执行任何操作与从不删除自己并始终期望 OnFinalRelease 执行删除之间做出明确的选择?一个比另一个更喜欢吗?
【问题讨论】:
标签: .net c++ visual-c++ com mfc