调用FindConnectionPoint时写入内存访问冲突

Access violation writing memory when calling FindConnectionPoint

本文关键字:内存 访问冲突 FindConnectionPoint 调用      更新时间:2023-10-16

我正在尝试订阅MBN Events。下面是我的代码:

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; 
        }
    }
}

由于文档(imho)有点缺乏,我在网上找到了一些代码示例。直到我调用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; 
}

此代码返回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这不是完全随机的。FindConnectionPointIConnectionPointContainer接口中的第二个表项,即v表中的第五个表项(占IUnknown的3个方法)。GetInterfaces方法占用了IMbnInterfaceManager中的相同位置。它的第一个参数是[out]形参,因此这解释了写时的访问冲突