当前位置: 首页 > 知识库问答 >
问题:

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

巫马修为
2024-06-26

使用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接口并不是空指针。

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

共有1个答案

石思淼
2024-06-26

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

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

 类似资料:
  • > 单击 受保护得空onPrepareDialog(int id,Dialog Dialog) 受保护的对话框onCreateDialog(int id) 如果我对timepickerdialog代码做了什么错误,请告诉我。

  • 实现 Deref trait 允许我们重载 解引用运算符(dereference operator)*(与乘法运算符或 glob 运算符相区别)。通过这种方式实现 Deref trait 可以被当作常规引用来对待,可以编写操作引用的代码并用于智能指针。 让我们首先看看 * 如何处理引用,接着尝试定义我们自己的类 Box<T> 类型并看看为何 * 不能像引用一样工作。我们会探索如何实现 Deref

  • 指针是C/C++区别于其他语言的最强大的语法特性,借助指针,C/C++可以直接操纵内存内容。但是,指针的引入也带来了一些使用上的困难,这要求程序员自己必须手动地对分配申请的内存区进行管理。 unique_ptr基本用法 unique_ptr是C++11提供的用于防止内存泄漏的智能指针中的一种实现,独享被管理对象指针所有权的智能指针。unique_ptr对象包装一个原始指针,并负责其生命周期。当该对

  • 大部分情况下所有权是非常明确的:可以准确的知道哪个变量拥有某个值。然而,有些情况单个值可能会有多个所有者。例如,在图数据结构中,多个边可能指向相同的结点,而这个结点从概念上讲为所有指向它的边所拥有。结点直到没有任何边指向它之前都不应该被清理。 为了启用多所有权,Rust 有一个叫做 Rc<T> 的类型。其名称为 引用计数(reference counting)的缩写。引用计数意味着记录一个值引用的

  • 指针 (pointer)是一个包含内存地址的变量的通用概念。这个地址引用,或 “指向”(points at)一些其他数据。Rust 中最常见的指针是第四章介绍的 引用(reference)。引用以 符号为标志并借用了他们所指向的值。除了引用数据它们没有任何其他特殊功能。它们也没有任何额外开销,所以应用的最多。 另一方面,智能指针(smart pointers)是一类数据结构,他们的表现类似指针,但

  • 问题内容: MyClass.java: 编译MyClass.java文件的SimpleCompileTest.java的清单。 SimpleCompileTest.java: 我正在执行SimpleCompileTest类并获取NullPointerException。ToolProvider.getSystemJavaCompiler()返回null。有人可以告诉我代码有什么问题吗 问题答案:

  • 我有两个类和,其中有一个名为的类型的成员变量。请注意,这没有声明为const。 在下面提供的最小示例中;当是指针时,那么一切都会编译并运行良好。如果我将其更改为非指针,那么我会得到编译器错误(这些更改在最小示例中被注释掉): “对常量对象调用了非常量函数“setOtherMember” 错误:通过'const其他类'作为'this'参数丢弃限定符[-fpermissive]m_otherClass

  • 我最近一直在用C++11智能指针替换所有的原始指针,现在我终于完成了,除了DirectX长指针。