兔子的技术博客

兔子

   :: 首页 :: 联系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新评论

阅读排行榜

评论排行榜

     刚才修改UI编辑器一个小功能,莫名其妙出现内存泄露。经过跟踪,发现是 _variant_t 在捣鬼,来看这句代码:
1    bool AddToCollection(IUnknown *lpiFile);
2    bool AddToCollection(VARIANT &varFile);
3    _variant_t GetDSFile();
4 
5    AddToCollection(GetDSFile());   // 这句将导致内存泄露!

     初看没什么问题,但上面的代码最后一句将的确导致内存泄露!
     改成如下方式后正常:
1     bool AddToCollection(IUnknown *lpiFile);
2     bool AddToCollection(VARIANT &varFile); 
3     _variant_t GetDSFile();
4 
5     _variant_t varFile = GetDSFile();
6     AddToCollection(varFile);   // 正常!

      进一步跟踪发现,第一种方式调用的 AddToCollection(IUnknown *lpiFile) ,检查 _variant_t 的重载代码如下:
 1 // Extracts a VT_UNKNOWN into an IUnknown*
 2 //
 3 inline _variant_t::operator IUnknown*() const 
 4 {
 5     if (V_VT(this) == VT_UNKNOWN) {
 6         if (V_UNKNOWN(this) != NULL) {
 7             V_UNKNOWN(this)->AddRef();    // 就是这里增加了引用计数
 8         }
 9         return V_UNKNOWN(this);
10     }
11 
12     _variant_t varDest;
13     varDest.ChangeType(VT_UNKNOWN, this);
14 
15     if (V_UNKNOWN(&varDest) != NULL) {
16         V_UNKNOWN(&varDest)->AddRef();    // 就是这里增加了引用计数
17     }
18 
19     return V_UNKNOWN(&varDest);
20 }

      注意到,上面的代码中有两处增加了引用计数!
      问题就出在这里!
      一般来讲,从函数返回值返回的 COM 指针是不增加引用计数的,如果调用者需要持有该指针,由调用者自己增加引用计数即可,但不知为何,这里会增加引用计数,不解!!!!!

      另外  GetDSFile() 返回的是 _variant_t ,为什么编译器要去调用  AddToCollection(IUnknown *lpiFile) ?  其实是因为 GetDSFile() 返回的是临时变量,临时变量优先匹配 const 的重载,所以将 bool AddToCollection(VARIANT &varFile); 改成 bool AddToCollection(const VARIANT &varFile); 也可以!!

posted on 2012-01-18 11:58 会飞的兔子 阅读(490) 评论(0)  编辑 收藏 引用 所属分类: C++及开发环境

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