随笔-90  评论-947  文章-0  trackbacks-0

最近有个东西,需要读 XML 配置文件,于是用 msxml 做了。msxml 是基于 COM 的,使用之前需要 CoInitialize,使用之后需要 CoUninitialize。于是我写成了:

void foo()
{
    CoInitialize(NULL);

    // Reading configuration

    CoUninitialize();
}

刚才我正乐此不彼的把类似这样的东西改成:

void foo()
{
    CoInitialize(NULL);
    LOKI_ON_BLOCK_EXIT(CoUninitialize);

    // Reading configuration
}

前面的同事过来看到了,说,你不该在这里调用 CoInitialize 和 CoUninitialize。如果有的地方也在用 COM,你这里 CoUninitialize 一下,别的地方就会出错了,上次的某个 Bug 就是。

我狡辩道:我假定这里没有多线程环境(实际上也是),并且约定别的地方用 COM 的时候调用 CoInitialize 时不要判断返回值。

同事:应该和大众习惯保持一致,最好就是全项目最开始的时候 CoInitialize 一次,结束的时候 CoUninitialize 一次。

我:我这里是较底层功能函数。

同事:可以以文档的方式注明,使用该模块前必须自己 CoInitialize,使用完毕后自己 CoUninitialize。

我:我只是想要用起来方便一点,用的时候不要有那么多先决条件和后置条件。再说,人家本来可以不知道我用了 COM,我这么一说明,就暴露了内部信息了不是?

其实我被动摇了。

各位大大,你们怎么处理呢?

------------------------------华丽的分割线(13:27 p.m. 增加)----------------------------------

好,既然 CoInitialize 和 CoUninitialize 有引用计数机制,那么这个具体问题已经解决。

那么,有没有类似的成对使用的 API,会对进程全局产生影响的呢?如果有,在底层要用到的时候该怎么处理?

posted on 2010-04-02 10:02 溪流 阅读(25052) 评论(17)  编辑 收藏 引用 所属分类: C++COM

评论:
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 10:21 | 游客~~
参照CoInitialize 的返回值,写个类,在够函数中根据前边的返回值情况判断是否调用 CoUninitialize  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 10:22 | 游客~~
@游客~~
是析构函数 刚才打错  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 11:07 | 陈梓瀚(vczh)
在某个cpp里面写

class FxxkCom
{
public:
FxxkCom()
{
CoInitialize();
}
~FxxkCom()
{
CoUninitialize();
}
} fxxkCom;  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 11:14 | WXX
你不该在这里调用 CoInitialize 和 CoUninitialize。如果有的地方也在用 COM,你这里 CoUninitialize 一下,别的地方就会出错了


这句话不对,如果配对了应该就不会有问题。我的原则是这种调用尽量在线程的初始化和反初始化的时候做,其他时间尽量不做这种事情。  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 12:49 | 溪流
@陈梓瀚(vczh)
@WXX
这个会不会影响其它线程?  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 12:52 | 溪流
哦,好像只对当前线程起作用。。。那问题就没有了,什么时候用什么时候调就可以了。

有没有会影响整个进程的这样的成对的函数呢?  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 12:52 | berg
放心好了,这两个函数内部维护了引用计数,只要配对使用就好。  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 13:22 | 溪流
@berg

果然!测试OK~~~  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 13:56 | Jakcie
类似于这样的初始化,的确应该放在整个工程的一开始和最后比较好。
例如,CoInitializeEx,OleInitialize,WSAStartup之类的,一开始就调用。最后释放。一开始如果调用不成功,也比较好处理。  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 15:56 | 溪流
@Jakcie
如果我在写库/底层函数呢?  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 16:02 | OwnWaterloo
我也这么干过:

class C{
C() {
CoInit()
}
~C() {
CoUnit()
}
...
};

为的也是让其他代码干净一些, 不要引入那些丑陋的头文件以及看到COM这么丑陋的东西。

全局数据初始化有不同的设计方法。
如果内部有引用技术, 就可以这么干。
如果没有, 就告诉C的使用者, 使用前需要怎样, 使用后又怎样。
  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-02 19:02 | 飞鸽传书
最好在构造与析构,可以保证他在先于控件创建,后于控件销毁。  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2010-04-13 02:27 | 欲三更
这个是引用计数的,没问题。
想想看,如果这个函数没有引用计数,那会带来无数的问题。  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2011-02-28 10:24 | gggg
我测试过,是没有关系的,只要两个东西配对,你想怎么调用都可以  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2011-03-08 16:17 | 溪流
@fixdot
对,当时也是这样的问题。也是原因不明。可是既然原因不明,那么作为论据其实有问题的。如果这两个函数确实有引用计数的,那么应该提倡用时CoInitialize,用完马上CoUninitialize。除非能够说出“一个进程里最好只调用一次”的道理。  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2011-03-08 18:50 | 溪流
@fixdot
为什么删除了?  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2011-03-31 09:56 | Wallace
@溪流
我的程序里面怎么不行,一个是EXCEL的类,其构造函数和析构函数里有相关的初始化和释放代码,另一个是ADO操作数据库的类,也有一对代码,可是只要一输出过EXCEL,那个ADO查询数据库的类就用不了。  回复  更多评论
  
# re: CoInitialize 和 CoUninitialize 的调用时机问题 2011-10-10 10:39 | daixi
你的同事说的是对的,最好是每个线程的开始一次CoInitialize,退出的时候一次CoUninitialize。否则的确会出一些乱七八糟的问题。曾经在这个事情上吃过亏,最后的解决办法就是只CoInitialize,不调CoUninitialize。哈哈哈哈。。。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理