COM规则允许每个接口实例进行引用计数吗?

时间:2014-08-01 01:33:27

标签: com oledb

我正在使用我正在编写的OLE DB提供程序从Excel中崩溃,原因似乎是在挖掘了一些反汇编后,由于它试图调用IDBInfo实例上的一个方法,该提供程序已被删除(因为它的引用计数下降到0)。

现在,在这个提供程序中,对我的任何接口上的QueryInterface的每次调用总是返回一个新的(C ++)对象(它将所有IUnknown方法委托给一个公共对象,该对象将COM对象表示为整个,除了IUnknown的情况,以便允许身份检查,并遵循COM规则),每个维护它自己的引用计数。

例如,给出了一个“现场直播”。来自我的提供者的IUnknown A(假设QueryInterface成功),

ISomeInterface* B;
ISomeInterface* C;
A->QueryInterface(IID_ISomeInterface, (void**)&B);
// B refcount = 1.

A->QueryInterface(IID_ISomeInterface, (void**)&C);
// C refcount = 1, B refcount unchanged.

C->Release();
// C refcount = 0, C is destroyed, B refcount unchanged.

C->SomeMethod(); // Will crash as C has been destroyed, even though there is an outstanding 'live' ISomeInterface instance on the same object (i.e. B).

根据http://msdn.microsoft.com/en-us/library/windows/desktop/ms693431%28v=vs.85%29.aspx,这似乎是一个有效的,如果奇怪的实现。

我实际上是在破坏COM规则吗?

1 个答案:

答案 0 :(得分:3)

AddRefRelease的处理方式是每个指针上的引用计数。每次复制指针时,都AddRef;每次你停止使用指针时,你Release。因此,当没有指向它的接口指针时,可以精确地销毁对象。

(实际上,这通常会有所优化,例如,在您将接口指针传递给完全在您控制之下的函数的情况下,您可能不会因函数参数而AddRef而烦恼{{1当函数返回时。)

要回答您的问题:在指针 Release的引用计数已转到C之后,执行0任何操作都是违法的。指针C->的生命周期已经结束,即使它指向的对象可能仍然存在。

实现界面的方式并没有什么不同,例如:它是否由C ++对象或其他任何东西支持。界面完全不透明,这是COM的核心概念之一。规则说,一旦指针的引用计数到达C,客户端就无法通过该指针进行任何进一步的调用。