关于DLL中调用COM的蛋疼问题

Alexander 2015-10-15 07:46:43
最近工作中遇到的头疼问题……

说明:想要把数据库的相关处理封装进一个类中
相关代码如下:


CDBService::CDBService()
{
CoInitialize(NULL);

m_pCon.CreateInstance(__uuidof(Connection));
m_pCmd.CreateInstance(__uuidof(Command));
}

CDBService::CDBService(const CDBService &ser)
{}

CDBService::~CDBService()
{
if (m_pCon->State&adStateOpen)
m_pCon->Close();

m_pCmd.Release();
m_pCon.Release();

CoUninitialize();
}

CDBService &CDBService::GetInstance()
{
static CDBService inst;

return(inst);
}

直接在工程内使用这个类是正常的,但把CDBService打包进一个DLL进行调用问题就来了:运行结束时程序会崩掉,并提示几个内存访问错误。

初步估计可能是ADO组件释放的时机有问题,还想请各位大神给个权威的说明。
...全文
159 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
牧童吃五谷 2015-10-25
  • 打赏
  • 举报
回复
你在类的析构函数中调用 CoUninitialize(...)退出了COM子系统,而你的GetInstance()中死的对象居然是static类型的,那么要在最后才释放的,所以先后顺序就不对了 建议不要做这种static 类型的变量(我编写过一个将近100万C++代码的程序,完全就不采用static)变量的
  • 打赏
  • 举报
回复
引用 5 楼 suwei2002 的回复:
[quote=引用 4楼珍惜生命远离CPP 的回复:]析构顺序问题。 增加个方法,应用退出的时候调用 ,让COM对象先释放
确实,把实例管理用指针实现就可以了,是不是说DLL资源释放之前COM服务可能已经停止了?[/quote] 静态变量析构时间在main结束之后,main结束之后 先执行哪个操作后执行哪个操作都是不确定的,也无法控制,在dll中的话可能更复杂。所以要自己控制顺序。
Saleayas 2015-10-16
  • 打赏
  • 举报
回复
如果你的主线程使用了 CoInitialize 的时候,在结束的时候,会呼叫 CoUninitialize 在关闭的时候。 假如这个线程在你使用之前已经被 Com 初始化了,很多主线程都会这样的。 那么就算你是有 CoInit ,那么你在退出的时候,你的 CoUninit 是不会关闭 Com 的。而是最初的 CoInit 函数对应的 CoUninit。 在最后的 CoUninit 才会结束 Com 的操作,比如著名的列集、散集操作和存根等等。 而此时你的 DLL 如果释放的话,那么会进入无效代码而导致内存崩溃。 如果你使用 Com 代码有代理和存根那么就不会有这个问题,系统自动处理这些问题。 或者,你不要主动使用卸载代码,而是让 Com 自动使用卸载。 如果你的主线程确保仅仅由你呼叫 CoInitialize,那么就可以解决这个问题。 你可以在你的线程中呼叫 CoInit 函数,看看返回值。
oyljerry 2015-10-16
  • 打赏
  • 举报
回复
引用 5 楼 suwei2002 的回复:
[quote=引用 4楼珍惜生命远离CPP 的回复:]析构顺序问题。 增加个方法,应用退出的时候调用 ,让COM对象先释放
确实,把实例管理用指针实现就可以了,是不是说DLL资源释放之前COM服务可能已经停止了?[/quote] 这个先后顺序应该是不能保证,所以要你显示的析构,而不是依赖析构函数
Alexander 2015-10-16
  • 打赏
  • 举报
回复
引用 4楼珍惜生命远离CPP 的回复:
析构顺序问题。 增加个方法,应用退出的时候调用 ,让COM对象先释放
确实,把实例管理用指针实现就可以了,是不是说DLL资源释放之前COM服务可能已经停止了?
  • 打赏
  • 举报
回复
析构顺序问题。 增加个方法,应用退出的时候调用 ,让COM对象先释放
oyljerry 2015-10-15
  • 打赏
  • 举报
回复
DLL中单独初始化一下com,以及设置对应的线程模型
Saleayas 2015-10-15
  • 打赏
  • 举报
回复
确保你的 DLL 在你的使用线程没有关闭之前不被卸载。
zgl7903 2015-10-15
  • 打赏
  • 举报
回复
Ole 有没有初始化? CoInitializeEx 等
miniblink是什么? Miniblink是一个追求极致小巧的浏览器内核项目,全世界第三大流行的浏览器内核控件。 其基于chromium最新版内核,去除了chromium所有多余的部件,只保留最基本的排版引擎blink。 Miniblink保持了10M左右的极简大小,是所有同类产品最小的体积,同时支持windows xp、npapi。 为什么要做miniblink? 市面上作为嵌入的组件的可用的浏览器内核,不外乎这几个:webkit、cef、nwjs、electron。 cef:优点是由于集成的chromium内核,所以对H5支持的很全,同时因为使用的人也多,各种教程、示例,资源很多。但缺点很明显,太大了。最新的cef已经夸张到了100多M,还要带一堆的文件。同时新的cef已经不支持xp了(chromium对应版本是M49)。而且由于是多进程架构,对资源的消耗也很夸张。如果只是想做个小软件,一坨文件需要带上、超大的安装包,显然不能忍受。 nwjs,或者最近大火的electron:和cef内核类似,都是chromium内核。缺点和cef一模一样。优点是由于可以使用nodejs的资源,同时又自带了各种api的绑定,所以可以用的周边资源非常丰富;而基于js的开发方案,使得前端很容易上手。所以最近N多项目都是基于nwjs或electron来实现。例如vscode,atom等等。 原版webkit:现在官网还在更新windows port,但显然漫不在心,而且最新的webkit也很大了,超过20几M。最关键的是,周边资源很少,几乎没人再基于webkit来做开发。同时由于windows版的saferi已经停止开发了,所以用webkit就用不了他的dev tools了。这是个大遗憾。 WKE:这是个很老的webkit内核的裁剪版了。小是小,但bug太多了。 那么关键点来了,使用miniblink有啥好处呢?? 首先,miniblink对大小要求非常严格。原版chromium、blink里对排版渲染没啥大用的如音视频全都被砍了,只专注于网页的排版和渲染。甚至为了裁剪大小,我不惜使用vc6的crt来跑mininblink(见我上篇文章)。这个也算前无古人后无来者了。 其次,miniblink紧跟最新chromium,这意味着chromium相关的资源都可以利用。在未来的规划里,我是打算把electron的接口也加上的,这样可以无缝替换electron。使用miniblink的话,开发调试时用原版electron,发布的时候再替换掉那些dll,直接可以无缝切换,非常方便。 miniblink如何使用? Miniblink导出了electron、WKE的接口,可以直接无缝替换现有的electron、WKE项目。 早期miniblink还导出了CEF接口,不过现在已被废弃。 miniblink有个小demo,从demo里可以看到,brackct这个基于cef的开源编辑器,已经顺利由miniblink跑起来了。现在electron的接口已做好,vscode跑起来了。 更详细的使用文档见本页其他文章。 miniblink如何裁剪到这么小? 这个比较复杂了。主要就是把blink从chromium抽离了出来,同时补上了cc层(硬件渲染层)。现在的blink,已经不是当年的那个webkit了,渲染部分全走cc层,复杂无比。我这大半年都在重写他那个又复杂的cc层。 和webkit比,miniblink架构有什么优势 现在的webkit版本,已经比miniblink落后太多了。blink一直在加入各种极富创造力和想象力的功能、组件。例如,blink早就加入多线程解析html token、blink gc回收器、多线程录制回放渲染机制。这些能让blink的解析渲染速度极大提升。下一次,我会先开源出blink gc组件,这东西很有意思,在c++里硬是搞出了一个垃圾回收机制,能让你像写java一样写c++。

3,248

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧