使用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接口并不是空指针。
所以...还有什么其他原因会导致该异常吗?以及如何解决该异常呢?
CoUninitialize 之后就不能再调用任何 COM 的 API 了,包括
ptr->Release()
。你的
pSmart
的析构是发生在 CoUninitialize 之后的,所以就出错了。