使用unique_ptr封装COM接口指针,当智能指针超出作用域时为何会出现异常?

新手上路,请多包涵

使用unique_ptr封装COM接口指针,当智能指针超出作用域时为何会出现异常?

异常为:0x00007FF664F12EEF 处有未经处理的异常(在 LearningCpp.exe 中): 0xC0000005: 读取位置 0x00007FF88546D588 时发生访问冲突。

//C++头文件
#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>
#include<vector>
#include<algorithm>
#include<set>
#include<array>
#include<memory>
#include<functional>
using namespace std;

//一些Windows头文件
#include<windows.h>
#include<sddl.h>
#include<Lm.h>
#pragma comment(lib, "netapi32.lib")
#include<aclapi.h>
#include<shlobj_core.h>
#include<shlwapi.h>
#include<windowsx.h>

//COM组件相关头文件
#include<objbase.h>
#pragma comment(lib,"Ole32.lib")
//Direct2D相关头文件
#include<d2d1.h>
#include <d2d1helper.h>
#pragma comment(lib,"D2d1.lib")
//WIC相关头文件
#include<wincodec.h>
#pragma comment(lib,"windowscodecs.lib")
//DWrite相关头文件
#include<dwrite.h>
#pragma comment(lib,"Dwrite.lib")


// 自定义删除器,用于 COM 对象的 Release  
struct ComDeleter {
    void operator()(IUnknown* ptr) const {
        if (ptr) {
            cout << ptr->Release();
        }
        else
            cout<<"空指针" << endl;
    }
};

int main() {
    //初始化COM库
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    IFileOpenDialog* pTemp = nullptr;
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTemp));
    if (FAILED(hr))
    {
        cout << "创建COM接口失败" << endl;
        return 0;
    }
    //使用unique_ptr封装COM接口指针
    using SmartCOMPtr = unique_ptr<IFileOpenDialog, ComDeleter>;
    SmartCOMPtr pSmart{ pTemp };

    //取消初始化COM库
    CoUninitialize();
    return 0;
}

百度了好几个可能的原因,都说是:指针为空指针,所以调用Release方法时报错。

但我这边也测试了CoCreateInstance函数的返回值、智能指针的删除器也做了空指针的判断,已经确定创建COM接口成功了,main函数中的代码如果直接改成:

int main() {
    //初始化COM库
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    IFileOpenDialog* pTemp = nullptr;
    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTemp));
    if (FAILED(hr))
    {
        cout << "创建COM接口失败" << endl;
        return 0;
    }

    cout << pTemp->Release() << endl;//输出:0

    //取消初始化COM库
    CoUninitialize();
    return 0;
}

直接调用接口的Release方法,是能正常运行的,说明创建的COM接口并不是空指针。

所以...还有什么其他原因会导致该异常吗?以及如何解决该异常呢?

阅读 1k
1 个回答

CoUninitialize 之后就不能再调用任何 COM 的 API 了,包括 ptr->Release()

你的 pSmart 的析构是发生在 CoUninitialize 之后的,所以就出错了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题