调用 FindConnectionPoint 时访问冲突写入内存
Access violation writing memory when calling FindConnectionPoint
我正在尝试订阅 MBN 活动。这是我的代码:
void subscribeToMbnEvents()
{
dwError = CoInitializeEx(NULL, COINIT_MULTITHREADED);
SAFEARRAY* mbnInterfaces;
CComPtr<IMbnInterfaceManager> intMgr = NULL;
dwError = CoCreateInstance(CLSID_MbnInterfaceManager, NULL, CLSCTX_ALL, IID_IMbnInterfaceManager, (void**)&intMgr);
if (dwError != ERROR_SUCCESS)
{
CoUninitialize();
std::cout << getTimeStamp() << " failed to initialize IMbnInterfaceManager \n";
}
dwError = intMgr->GetInterfaces(&mbnInterfaces);
if (dwError != ERROR_SUCCESS)
{
CoUninitialize();
std::cout << getTimeStamp() << " failed to get MBN Interfaces \n";
}
if (dwError == ERROR_SUCCESS)
{
LONG indexOfFirstMBNInterface;
dwError = SafeArrayGetLBound(mbnInterfaces, 1, &indexOfFirstMBNInterface);
if (dwError != ERROR_SUCCESS)
{
std::cout << getTimeStamp() << " failed to get first index of MBN Interface \n";
}
CComPtr<IMbnInterface> MbnInt = NULL;
dwError = SafeArrayGetElement(mbnInterfaces, &indexOfFirstMBNInterface, (void*)(&MbnInt));
if (dwError != ERROR_SUCCESS)
{
std::cout << getTimeStamp() << " failed to get MBN Interface \n";
}
IConnectionPointContainer* icpc;
dwError = intMgr->QueryInterface(IID_IMbnInterfaceManager, (void**)&icpc);
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error querying interface" << std::endl;
}
IConnectionPoint *icp;
dwError = icpc->FindConnectionPoint(IID_IMbnInterfaceEvents, &icp);
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error finding connection point" << std::endl;
}
}
}
由于文档(恕我直言)有点缺乏,所以我将自己定位于在网上找到的一些代码示例。直到我调用 FindConnectionPoint
一切正常。当调用 FindConnectionPoint
时,我得到一个写入内存的访问冲突,所以我猜问题出在我的 IConnectionPoint
指针上,它在我发现的多个代码示例中被声明。
希望有更多监督的人能够帮助解决这个问题。提前致谢
检索IConnectionPointContainer
的代码是错误的:
IConnectionPointContainer* icpc;
dwError = intMgr->QueryInterface(IID_IMbnInterfaceManager, (void**)&icpc);
// ^^^^^^^^^^^^^^^^^^^^^^^^ wrong interface ID
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error querying interface" << std::endl;
}
此代码 returns 一个 IMbnInterfaceManager
接口,但将其重新解释为 IConnectionPointContainer
。当它继续执行icpc->FindConnectionPoint
时,它真的是在调用IMbnInterfaceManager
1.
的随机接口方法
要解决这个问题,需要将代码更改为:
IConnectionPointContainer* icpc = nullptr;
HRESULT hr = intMgr->QueryInterface(IID_ConnectionPointContainer, (void**)&icpc);
if (FAILED(hr))
{
std::cout << "Error querying interface" << std::endl;
}
使用 IID_PPV_ARGS 宏更简单、更安全。它推导出与指针类型匹配的接口ID:
HRESULT hr = intMgr->QueryInterface(IID_PPV_ARGS(&icpc));
1 这不是完全随机的。 FindConnectionPoint
是 IConnectionPointContainer
接口中的第二个条目,即 v-table 中的第五个条目(占 3 IUnknown
方法)。 IMbnInterfaceManager
中的相同位置被 GetInterfaces 方法占用。它的第一个参数是 [out] 参数,因此可以解释写入时的访问冲突。
我正在尝试订阅 MBN 活动。这是我的代码:
void subscribeToMbnEvents()
{
dwError = CoInitializeEx(NULL, COINIT_MULTITHREADED);
SAFEARRAY* mbnInterfaces;
CComPtr<IMbnInterfaceManager> intMgr = NULL;
dwError = CoCreateInstance(CLSID_MbnInterfaceManager, NULL, CLSCTX_ALL, IID_IMbnInterfaceManager, (void**)&intMgr);
if (dwError != ERROR_SUCCESS)
{
CoUninitialize();
std::cout << getTimeStamp() << " failed to initialize IMbnInterfaceManager \n";
}
dwError = intMgr->GetInterfaces(&mbnInterfaces);
if (dwError != ERROR_SUCCESS)
{
CoUninitialize();
std::cout << getTimeStamp() << " failed to get MBN Interfaces \n";
}
if (dwError == ERROR_SUCCESS)
{
LONG indexOfFirstMBNInterface;
dwError = SafeArrayGetLBound(mbnInterfaces, 1, &indexOfFirstMBNInterface);
if (dwError != ERROR_SUCCESS)
{
std::cout << getTimeStamp() << " failed to get first index of MBN Interface \n";
}
CComPtr<IMbnInterface> MbnInt = NULL;
dwError = SafeArrayGetElement(mbnInterfaces, &indexOfFirstMBNInterface, (void*)(&MbnInt));
if (dwError != ERROR_SUCCESS)
{
std::cout << getTimeStamp() << " failed to get MBN Interface \n";
}
IConnectionPointContainer* icpc;
dwError = intMgr->QueryInterface(IID_IMbnInterfaceManager, (void**)&icpc);
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error querying interface" << std::endl;
}
IConnectionPoint *icp;
dwError = icpc->FindConnectionPoint(IID_IMbnInterfaceEvents, &icp);
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error finding connection point" << std::endl;
}
}
}
由于文档(恕我直言)有点缺乏,所以我将自己定位于在网上找到的一些代码示例。直到我调用 FindConnectionPoint
一切正常。当调用 FindConnectionPoint
时,我得到一个写入内存的访问冲突,所以我猜问题出在我的 IConnectionPoint
指针上,它在我发现的多个代码示例中被声明。
希望有更多监督的人能够帮助解决这个问题。提前致谢
检索IConnectionPointContainer
的代码是错误的:
IConnectionPointContainer* icpc;
dwError = intMgr->QueryInterface(IID_IMbnInterfaceManager, (void**)&icpc);
// ^^^^^^^^^^^^^^^^^^^^^^^^ wrong interface ID
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error querying interface" << std::endl;
}
此代码 returns 一个 IMbnInterfaceManager
接口,但将其重新解释为 IConnectionPointContainer
。当它继续执行icpc->FindConnectionPoint
时,它真的是在调用IMbnInterfaceManager
1.
要解决这个问题,需要将代码更改为:
IConnectionPointContainer* icpc = nullptr;
HRESULT hr = intMgr->QueryInterface(IID_ConnectionPointContainer, (void**)&icpc);
if (FAILED(hr))
{
std::cout << "Error querying interface" << std::endl;
}
使用 IID_PPV_ARGS 宏更简单、更安全。它推导出与指针类型匹配的接口ID:
HRESULT hr = intMgr->QueryInterface(IID_PPV_ARGS(&icpc));
1 这不是完全随机的。
FindConnectionPoint
是 IConnectionPointContainer
接口中的第二个条目,即 v-table 中的第五个条目(占 3 IUnknown
方法)。 IMbnInterfaceManager
中的相同位置被 GetInterfaces 方法占用。它的第一个参数是 [out] 参数,因此可以解释写入时的访问冲突。