• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >vc/mfc > [求助]初学COM,用CComPtr导致运行出现异常,无解

[求助]初学COM,用CComPtr导致运行出现异常,无解

作者:佚名 字体:[增加 减小] 来源:互联网 时间:2017-06-04

佚名通过本文主要向大家介绍了ccomptr,ccomptr 头文件,ccomptr idispatch,ccomptr 用法,丁香园文献求助等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
问题: [求助]初学COM,用CComPtr导致运行出现异常,无解
描述:

在不用CComPtr的代码,没有错误.
void InvokeTest2()
{
HRESULT hr = NULL;
ISimpleMath* pSimpleMath = NULL;
hr=CoInitialize(NULL);
if(!SUCCEEDED(hr))
{
return ;
}
hr = CoCreateInstance(CLSID_Math,
NULL,
CLSCTX_INPROC_SERVER,
IID_ISimpleMath,
(void**)&pSimpleMath);
if(SUCCEEDED(hr))
{
int val_1 = 4;
int val_2 = 6;
int ret_val = 0;
int* ret_pval = &ret_val;
pSimpleMath->Add(val_1, val_2,ret_pval);
}
::CoUninitialize();
}
引入CComPtr出现异常.
void InvokeTest1()
{
HRESULT hr = NULL;
CComPtr<IUnknown> spUnknown;
CComPtr<ISimpleMath> spSimpleMath;
hr=CoInitialize(NULL);
if(!SUCCEEDED(hr))
{
return ;
}
hr = spUnknown.CoCreateInstance(CLSID_Math);
hr = spUnknown.QueryInterface( &spSimpleMath );
if(SUCCEEDED(hr))
{
int val_1 = 4;
int val_2 = 6;
int ret_val = 0;
int* ret_pval = &ret_val;
spSimpleMath->Add(val_1, val_2,ret_pval);
}
::CoUninitialize();
}
Call Stack 内容为:
  ~CComPtrBase() throw()
  {
     if (p)
p->Release(); //弹出异常的地方,
                       //Unhandled exception:Access violation reading location
  }
   MyClient.exe!ATL::CComPtrBase<ISimpleMath>::~CComPtrBase<ISimpleMath>()  
   MyClient.exe!ATL::CComPtr<ISimpleMath>::~CComPtr<ISimpleMath>()  
不知道为什么,怎么解决?
请高手指教?
谢谢!!


解决方案1:

呵呵,想来这个问题就不是三言两语能解决的。
佩服ks_gq兄的耐心,我也再多说点吧。
其实从语义及规范使用上来讲,ks_gq兄的说法是正确的,我们不能只拉屎而不擦屁股(只去初始化而不去释放)。
CoInitialize(Ex)的作用分为两个:载入COM所需的DLL和将调用线程纳入指定的套间并初始化相关数据。相应的,CoUninitialize的作用也可以理解为退出套间和卸载COM DLL。
经过调试查看,由于效率的原因,COM DLL一旦被载入,将会一直映射在内存地址空间中,直到进程退出,所以CoUninitialize的卸载作用是不存在的。也就是说,如果忽略掉第一次CoInitialize(Ex)的调用所起的载入COM DLL的作用,这两个API的作用就限制到了线程的层面:将线程纳入套间和退出套间。
而根据windows的一贯作风(在进程、线程退出时自动执行相关的清理工作),我们应该不用担心如果不调用CoUninitialize,线程将不会退出套间。因此不调用CoUninitialize就正如不关闭打开的文件一样,虽然进程(线程)退出时会保证清理动作的执行,但终究不是良好的行为。
因此在此处,不调用CoUninitialize可以说是最快的解决办法,但不是最好的解决办法。
另外导致最后非法内存访问的原因应该是因为线程退出套间时卸载掉了COM对象所在的DLL,因此对象的内存变为无效。

解决方案2:

在CoUninitialize()之前调用spUnknown.Release();spSimpleMath.Release();是不会出错的, 因为智能指针是利用C++对象会自动调用析构的原理实现的, 而析构是发生在函数体外, 也就是'}'之后, 而你在函数的末尾调用了CoUninitialize(),也就是在函数结束之前,你已经卸载了COM库, 所以在函数结束之后智能指针在执行自己的析构函数的时候当然会出错(com库已经被卸载), 这就是你程序出错的原因, 而在CoUninitialize之前我们手动释放, 在智能指针自动调用自己析构函数的时候就不会出错了,   呵呵, 去掉CoUninitialize是不对的, COM库没有被卸载~~~~
最好的解决方法是不要在这个函数的头和尾调用CoInitialize(NULL)和CoUninitialize(), 最好在程序的初始化和程序结束的时候调用, 这样就不会出现你所描述的错误了, 也可以更好的利用智能指针, 不用自己去手动释放.  这是我的原意, 你可能理解错了.


分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 为什么用CComPtr<IObj>创建的对象不能Release,而用IObj创建对象指针,就可以Release?
  • CComPtr与_com_ptr_t模板
  • CComPtr什么时候需要release?
  • 程序中用了CComPtr的话,还需要CoInitialize和CoUninitialize吗?
  • CComPtr未定义;atlcomhrequiresatlbasehtobeinclud
  • CComQIPtr比CComPtr的好处在于哪里?不再需要显示调用QueryInterface了?
  • CComPtr指针的构造函数是不是已经包含了CoCreateInstance了?
  • _ApplicationPtr和CComPtr的区别
  • CComPtr<I>sp能否作为函数参数传递?
  • "focus”:不是“ATL::_NoAddRefReleaseOnCComPtr<T>”的成员的原因?

相关文章

  • 2017-06-05 多媒体时间函数
  • 2017-06-04 ActiveX控件产生窗口的问题
  • 2017-06-04 MMC控制台程序应该怎么写?
  • 2017-06-04 纯COM使用方法疑问100分答谢
  • 2017-06-05 大家有兴趣做一做?
  • 2017-06-05 我怎样在一个线程中Suspend这个线程
  • 2017-06-05 vc中隐藏excel工具栏和菜单栏
  • 2017-06-05 送分!正在学习多线程!谁有例子?
  • 2017-06-05 如何调用Acitvex,非对话框下
  • 2017-06-04 這個dll怎么寫?

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 十万火急,在线等。高手大侠快进来。。。。。。。。。。。。。。。。。
    • 用API钩子怎么才能得到sendto第二个参数的内容?
    • c++的问题~~~~~~~~~~~~~~~~~~~~~请教高人~~~~~~~~~~~~~~谢谢!
    • 有谁知道sqlite图形化工具怎么执行indices等自带命令,不是sql语言
    • 用ATL写的Service程序,前台程序如何调用MFC
    • 求signcodeexe,cert2spc等下载地址,谢谢!
    • 如何获得所有进程的完整路径?
    • COM调用问题
    • 疑问:关于web服务器端activex的线程模型
    • 结构化存储中能多个同时打开同一个Stream进行读吗

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有