我正在使用服务来检测头部集的连接。当麦克风连接和断开时,我收到通知。问题是,当我手动结束服务时, 在做SAFE_RELEASE时,我正面临服务崩溃。 这是代码......
NotifyHandsetConnectionStatus::NotifyHandsetConnectionStatus() : _cRef(1), _pEnumerator(NULL){}
NotifyHandsetConnectionStatus::~NotifyHandsetConnectionStatus()
{
// SAFE_RELEASE(_pEnumerator)
if (_pEnumerator)
{
_pEnumerator->Release(); // CRASH
_pEnumerator = NULL;
}
}
void NotifyHandsetConnectionStatus::Init(DWORD threadID)
{
PTTThreadID = threadID;
HRESULT hr = S_OK;
CoInitialize(NULL);
if (_pEnumerator == NULL)
{
// Get enumerator for audio endpoint devices.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator), (void**)&_pEnumerator);
}
if (hr == S_OK)
{
_pEnumerator->RegisterEndpointNotificationCallback(this);
}
}
这是类声明......
class NotifyHandsetConnectionStatus : public IMMNotificationClient
{
LONG _cRef;
IMMDeviceEnumerator *_pEnumerator;
DWORD PTTThreadID;
public:
NotifyHandsetConnectionStatus();
~NotifyHandsetConnectionStatus();
void Init(DWORD threadID);
ULONG STDMETHODCALLTYPE AddRef() override;
virtual ULONG STDMETHODCALLTYPE Release() override;
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) override;
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override;
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) override
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) override
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) override
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged( EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) override
{
return S_OK;
}
};
答案 0 :(得分:4)
您发布的代码不会崩溃,即使没有取消注册回调也不会崩溃。通过复制粘贴检查您所拥有的内容并添加您没有的内容。缺少IUnknown方法,但不太可能与它有任何关系。只需确保不会经常调用Release()函数,delete this
只能运行一次。
这样的代码有很多原因导致崩溃,堆损坏是每个C ++程序员讨厌的吵闹的邻居,他永远最有可能出现在最不合时宜的时刻。由于程序退出很可能是让邻居将拨号转为11,所以当你触摸堆部分时,你需要一段时间不需要。很难调试,腐败发生得更早。
隔离问题,首先将服务转变为通过所有相同动作的控制台模式应用程序,以便更容易调试。您可以使用UMHD.exe等堆诊断工具。为单个代码块编写单元测试。
答案 1 :(得分:0)
似乎需要 Unregister the IMMDeviceEnumerator before calling Release()
。
_pEnumerator->UnregisterEndpointNotificationCallback(this);