我应该如何检查 COM 中的 [out] params 是否可以使用?
按照官方规定,除非函数成功,否则不应使用 COM 函数中的 [out]
参数,这意味着(至少)有三种方法可以查看 [out]
参数是否可以使用。
考虑以下界面
interface IFoo : IUnknown {
HRESULT GetOtherFoo([out] IFoo** ppFoo);
HRESULT Bar();
};
您建议使用以下哪种方式?
1. 检查返回值
CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr))
other->Bar();
这让我有点紧张,因为 IFoo
中的错误可能会导致 NULL
指针取消引用。
2. 检查输出参数
这取决于这样一个事实:如果方法失败,则不得更改任何[out]
参数(如果参数更改了<==>它是安全的使用它)。
CComPtr<IFoo> other;
foo->GetOtherFoo(&other);
if (other)
other->Bar();
请注意,无论如何都会发生这种情况,如果指针不是 NULL,CComPtr
的析构函数将调用 Release
,因此它不可能是垃圾。
3. 偏执的方式,检查两者
CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr) && other)
other->Bar();
在我看来这有点冗长。
PS 请参阅相关问题。
Officially one should not use [out]
parameters from COM functions unless the function succeeded this means that there are (at least) three ways to see if an [out]
parameter can be used.
Consider the following interface
interface IFoo : IUnknown {
HRESULT GetOtherFoo([out] IFoo** ppFoo);
HRESULT Bar();
};
Which of the following ways would you recommend on using it?
1. Check return value
CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr))
other->Bar();
This makes me a bit nervous since a bug in IFoo
could cause a NULL
pointer dereferencing.
2. Check the output parameter
This depends on the fact that if a method fails it mustn't change any of the [out]
parameters (if the parameter changed <==> it's safe to use it).
CComPtr<IFoo> other;
foo->GetOtherFoo(&other);
if (other)
other->Bar();
Note that this sort of happens anyway, CComPtr
's destructor will call Release
if the pointer isn't NULL
so it can't be garbage.
3. The paranoid way, check both
CComPtr<IFoo> other;
HRESULT hr = foo->GetOtherFoo(&other);
if (SUCCEEDED(hr) && other)
other->Bar();
This is a bit verbose in my opinion.
P.S. See related question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您愿意编写更多检查并使代码慢一点以使其更可靠,则选项 3 适合您。 由于您预计 COM 服务器中存在错误,因此检查它们是非常合理的。
If you are willing to write more checks and make code a bit slower for making it more reliable option 3 is for you. Since you expect that there are bugs in the COM server it is quite reasonable to check against them.
返回成功 HRESULT 但将某些输出参数设置为 NULL 的 COM 服务器方法并不常见。 有几种情况(我想到的是 IClientSecurity::QueryBlanket),但通常如果方法成功返回,客户端可能期望所有输出参数都为非 NULL。
毕竟,这是如何记录该方法的问题。 然而,在默认情况下,我认为 1. 是一种安全的方法。
COM server methods that return a success HRESULT, yet set some of their output parameters to NULL are not very common. There are a few cases (IClientSecurity::QueryBlanket comes to mind) where this is used, but usually the client may expect all output parameters to be non-NULL if the method returned successfully.
It is, after all, a matter of how the method is documented. In the default case, however, I would consider 1. to be a safe way to go.