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

COM规则允许对每个接口实例进行引用计数吗?,com,oledb,Com,Oledb,当Excel使用我正在编写的OLE DB提供程序时,我从Excel中得到一个崩溃,原因似乎是,在经过一些反汇编之后,由于它试图调用IDBInfo实例上的一个方法,而该提供程序已被删除(其引用计数降至0) 现在,在此提供程序中,在我的任何接口上对QueryInterface的每次调用都会返回一个新的(C++)对象(它将所有IUnknown方法委托给一个公共对象,该对象表示COM对象作为一个整体,IUnknown除外,以便允许身份检查,并遵循COM规则),每个都维护自己的引用计数 例如,给定我的提供

当Excel使用我正在编写的OLE DB提供程序时,我从Excel中得到一个崩溃,原因似乎是,在经过一些反汇编之后,由于它试图调用IDBInfo实例上的一个方法,而该提供程序已被删除(其引用计数降至0)

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

例如,给定我的提供者提供的“实时”IUnknown a(并假设QueryInterface成功)

据我所知,这似乎是一个有效的(尽管奇怪)实现


我真的违反了COM规则吗?

应该将
AddRef
Release
视为每个指针上的引用计数。每次复制指针时,您都需要添加ref
AddRef
;每次停止使用指针时,您都会
释放
。因此,当没有指向该对象的接口指针时,可以精确地销毁该对象

(在实践中,这通常是经过一些优化的,例如,在将接口指针传递给完全由您控制的函数的情况下,您可能不必费心为函数参数
AddRef
,并在函数返回时
Release

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


< >如何实现接口没有什么区别,例如它是否被C++对象或其他东西支持。接口是完全不透明的,这是COM的核心概念之一。规则规定,一旦指针的refcount到达
0

对不起,我的工作有点马虎,客户端就不能通过该指针进行任何进一步的调用。当我说“新对象”时,我指的是一个新的C++对象,它将所有的IDENM方法委托给另一个对象,它由一个概念COM对象的所有接口共享。@ BWMANK OK,从我的帖子中删除了关于聚合的东西。是的,引用计数是每个接口,所以QueryInterface可以返回一个新对象,除非查询IUnknown。确保您遵守其他QI规则:它们更容易用一个对象实现。PS:如果你正在使用VisualStudio和C++,我建议你使用ATL,一旦你了解了它的工作原理,它会为你做所有的事情。在这个域中更容易出错。这些接口指针被称为撕裂,它们是完全有效的。无效的一点是使每个新查询的接口指针具有单独的状态,例如,如果SomeMethod()具有副作用,则无论是由B还是C调用,它们都应以相同的方式影响对象。允许单元间查询接口缓存接口指针,因此在另一方面,B和C可以是相同的接口指针(当两者都处于活动状态时,您将看到refcount为2)。
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).