问题内容:关于COM计数器 (AddRef()和Release())的问题。 我在一个函数中获取一个com的接口指针(Item),并将它返回。如下:我在外面对这个函数进行调用时,我写下下面两种代码,都可以通过,为什么?
- 原讨论链接:http://community.csdn.net/expert/topicview1.asp?id=801615
- 所属论坛:ATL/ActiveX/COM 审核组:VC/MFC
- 提问者:COM_MOC 解决者:wistaria
- 感谢:joke100
- 关键字:VC/MFC 函数 调用 控件 字段 触发器 变量 语句 堆栈 窗体 ATL/ActiveX/COM COM基础 正则
- 答案:
调用函数:
ItemType* fnGetItem()
{
...
ItemType* Item = NULL;
if( !SUCCEEDED( hr = GetItem(&Item) ) )
{//COM内部计数器自动加1,是吧?
AfxMessageBox("Error");
}
return Item;
}
代码片段1:
....
ItemType* Item1 = NULL;
Item1 = fnGetItem();
Item1->AddRef();
....
Item1->Release();
代码片段2:
....
ItemType* Item1 = NULL;
Item1 = fnGetItem();
//Item1->AddRef();不要这行语句程序也能运行。
....
Item1->Release();
wistaria Answer:
每当 QueryInterface 为一个对象分配一个新指针时,QueryInterface 有责任在返回该指针前调用 AddRef。这就是为什么不必为得到的指针调用 AddRef。
(注意,CoCreateInstance 调用 QueryInterface,而 QueryInterface 调用 AddRef,所以对象的第一个接口指针也是这样。)
如果您复制了一个接口指针,则需要调用 AddRef,这样该接口的引用计数才准确。
joke100 Answer:
首先你自己要注意addref和release的配对使用,尤其是自己写的时候,当调用其他代码时,要知道别人的代码是否已经调过addref了,一定要保证你的工程里使用同一套规范。
象前面的例子比较简单,因为fnGetItem内部已经addref,所以外部要多一次release.
第一种写法会导致Item1总在内存中不被释放,直到整个程序退出,由系统来释放,
第二种才是正确的。