Interface 为什么AddRef()和Release()的返回类型不是HRESULT

Interface 为什么AddRef()和Release()的返回类型不是HRESULT,interface,com,iunknown,Interface,Com,Iunknown,我最近开始学习COM。在COM中,函数的返回类型应为HRESULT。已经阅读了关于HRESULT,GetLastError()的问题,但是为什么,IUnknown的函数,AddRef()和Release()具有返回类型ULONG 我得出的答案是,AddRef()几乎总是从QueryInterface()调用,客户端不应该调用它。对于Release(),其返回值从不检查 虽然我可以用我自己的答案来反驳- 对于AddRef(),客户端可能需要调用它。既然客户端可以访问该函数,那么如何保证客户端不会调

我最近开始学习COM。在COM中,函数的返回类型应为HRESULT。已经阅读了关于
HRESULT
GetLastError()
的问题,但是为什么,IUnknown的函数,
AddRef()
Release()
具有返回类型
ULONG

我得出的答案是,
AddRef()
几乎总是从
QueryInterface()
调用,客户端不应该调用它。对于
Release()
,其返回值从不检查

虽然我可以用我自己的答案来反驳- 对于
AddRef()
,客户端可能需要调用它。既然客户端可以访问该函数,那么如何保证客户端不会调用它呢

对于
Release()
-同样,用户可以检查其返回类型,因为他可以

请澄清

还有,它是否像-->它的约定一样为COM相关函数使用HRESULT返回类型,而不是强制-->如果这是真的,它将停止我大脑中的混乱

“AddRef和Release永远不会失败,因此拥有它们没有任何意义 返回HRESULT。“-Igor Tandetnik


我将此作为一个答案发布,只是因为我的眼睛在阅读整个问题和所有评论时流着血,希望能帮助别人。。。来吧,社区,让我们结束这类问题。帮助没有这些垃圾的人筛选会容易得多。

我问自己一个类似的问题:为什么界面中需要3个方法而不是2个?QueryInterface和Release应该足够了。QI已经做了AddRef,理论上我们有两种方法来做基本相同的工作,其中一种应该被淘汰。气做它的事加上AddRef。AddRef只做AddRef。AddRef死了。接吻

对于返回类型,我不同意AddRef/Release永远不会失败的评论。嗯,他们可以。以几种不同的方式,它们应该遵循相同的HRESULT返回规则,并在参数中生成结果

AddRef失败的一个方法是,您可以超过ULONG_MAX(很难实现,但可能)。或者,用于使调用线程安全的信号量可以引发异常。事实上,很多事情都可能出错,因此我可以想象规范之所以将其设置为ULONG(void)的唯一原因是性能,因为调用一个没有参数的方法要容易得多

客户端性能早在90年代就已经是一个问题了,现在肯定不再是一个问题了(除非你说的是受限客户端,比如移动设备)。通过以性能为名牺牲语义,COM设计实际上造成了长期的维护负担,而牺牲了短期的性能增益,这一点大家都知道,也知道这一点一直在消失(摩尔定律,以相同的成本,容量每18个月翻一番)

但即便如此,AddRef也不应该如此频繁地被调用。这样做意味着您在系统的多个部分携带相同的对象,这本身就是一个糟糕设计的强烈标志


我也不同意这是一个糟糕的问题。这是一个好问题,因为它让人们思考。回答特定问题也是如此,因为人们会陷入困境。然而,让人们思考宽泛的/开放式的问题会教给他们一些技能,这些技能将首先防止他们陷入困境。

AddRef
Release
永远不会失败,因此让他们返回
HRESULT
是没有意义的。关于您的最后一个问题:方法不必返回
HRESULT
(尽管如果愿意,它们可以返回);所有其他方法必须返回
HRESULT
。这是因为封送层需要能够报告自己的错误(例如,如果调用跨越计算机边界且无法访问远程主机,则网络故障)
AddRef
Release
[本地]
,不需要成功/失败状态(参见上面的Igor),返回值被重新用于指示参考计数器的有用内容。这使得这些非常常用的方法轻量级且性能高效。@IgorTandetnik感谢您的回复。尽管如此,我仍然认为客户端可能需要调用
AddRef()
。例如,假设客户端具有本地接口指针,该指针将由服务器返回的有效接口指针分配。如果客户端和服务器都是两个不同的进程,那么它们的地址空间也会不同。因此,如果
pIOne
是由服务器发送的,并且
pIOneTemp
是本地的,那么在语句
pIOneTemp=pIOne之后,客户端将不得不调用
pIOneTemp
上的
AddRef()
,因为它位于完全不同的地址空间中。现在,为什么它不应该返回
HRESULT
?@romar。但为什么这不是一致性的突破呢?如果COM要求我们编写的方法的返回类型为
HRESULT
,则它自己的IUnknown方法仅不遵循规则。另请参见我上面的评论,并解释如果出现这种情况会发生什么?我从未说过客户不必调用
AddRef
。你觉得我的评论哪一部分可以这样理解?如果客户端从未调用过
AddRef
,那么
IUnknown
接口一开始就不会提供
AddRef
。但是这些与返回
HRESULT
有什么关系呢?书本上有没有法律规定任何可以调用的方法都必须返回
HRESULT