在 COM 对象上调用 Release 似乎永远不会返回

Posted

技术标签:

【中文标题】在 COM 对象上调用 Release 似乎永远不会返回【英文标题】:Calling Release on COM object never appears to return 【发布时间】:2016-06-13 16:56:13 【问题描述】:

我正在调试客户网站上的间歇性问题。我已经明白了,对 COM 对象的Release() 调用似乎没有返回。

第一个日志正在打印,但我从未看到第二个日志。我只能假设对Release() 的调用由于某种原因从未返回(或者可能是CoInitializeEx())。

我不知道接下来要寻找什么,任何帮助/线索将不胜感激。

Logger::getLogger()->logTrace("AudioCapturer::_shutdown. _pEndpointAudioClient_COM Released. (%s)", _deviceName.c_str());
releaseComObject(_pAudioCaptureClient_COM);
Logger::getLogger()->logTrace("AudioCapturer::_shutdown (%s) succeeded", _deviceName.c_str());

这里是支持代码:

IAudioCaptureClient *_pAudioCaptureClient_COM;

// Class that Initializes COM on creation and Unitializes on destruction
AutoCOM::AutoCOM()  CoInitializeEx(NULL, COINIT_MULTITHREADED); 
AutoCOM::~AutoCOM()  CoUninitialize(); 


#define AUTO_COM_SUPPORT AutoCOM _autoCOM

// Safe releasing of COM objects. Zeros the pointer
// to the COM object. Safe to use with NULL
// pointers.
template <class T> void releaseComObject(T*& pT) 
     if (pT) 
           AUTO_COM_SUPPORT;
           (pT)->Release();
           pT = NULL;
     

【问题讨论】:

MSDN 文档对 IAudioCaptureClient::Release() 有一个非常具体的警告。引用:“当释放 IAudioCaptureClient 接口实例时,客户端必须从与创建对象的 IAudioClient::GetService 调用相同的线程中调用实例的 Release 方法。”违反这样的要求很可能会导致死锁。 如果CoInitializeEx 调用失败,你仍然在做CoUnitialize,这是错误的。 #define AUTO_COM_SUPPORT AutoCOM 哇,你不想那样做。 releaseComObject 应该知道 COM 已经初始化或者 pT 来自哪里?把AUTO_COM_SUPPORT拿出来烧掉。 @HansPassant,谢谢。看起来Release() 是从不同的线程调用的。我会修复它,看看是否有帮助。 真的,AutoCom 宏需要在火灾中死掉。 【参考方案1】:

从未发现此问题的重复场景。但是@Cheersandhth.-Alf 提到的智能指针用户避免了这个问题。感谢您的反馈。

基本使用下面的宏来定义智能指针,并去掉了所有对Release()的引用

_COM_SMARTPTR_TYPEDEF(IMyInterface, __uuidof(IMyInterface));

【讨论】:

以上是关于在 COM 对象上调用 Release 似乎永远不会返回的主要内容,如果未能解决你的问题,请参考以下文章

python多线程-Semaphore(信号对象)

在 Android Studio 中永远不会调用 onLocationUpdate

aSmack MessageListener 的 processMessage 永远不会被调用

永远不会调用Django管理界面中的字段的只读方法

GraphQL 解析器问题

多线程-生产者消费者