我应该强制out-parameters为非NULL吗?

时间:2014-07-01 23:46:35

标签: com

IDL中的示例方法:

HRESULT _stdcall a_method( [in] long value, [out] BSTR *comment );

我的功能逻辑是,对于某些值,不需要注释。如果客户端使用comment == NULL调用此函数,是否应抛出异常?或许可以宽容并允许这种情况?

(我用C ++开发我的对象)。

我试图严格执行参数检查的理由是,我关注内存泄漏,以及让客户端根据COM规范调用正确但我的对象不接受调用。

1 个答案:

答案 0 :(得分:3)

[out]参数的语义非常明确。

获取[out]参数的方法永远不应该 - 看看参数的值,直到它在其上放置一些东西。这是未初始化的记忆。垃圾。事实上,如果你的方法是通过编组调用(公寓间或进程间)调用的,那么垃圾就是你得到的:无论你的调用者在调用你的方法时放在那里,被丢弃并被代理忽略/存根;你永远不会得到它。

如果客户端/调用者在调用方法之前在参数上添加了某些东西,那肯定是内存泄漏(当然它是一个像BSTR一样的分配对象),但它&#39是来电者的错。处理它并不是被调用方法的责任。即使它想要,被调用的方法也无法处理泄漏。

如果要处理调用者可能传入的任何值,则需要使用[in, out]参数而不是[out]

最后一个警告:自动化客户端(VBA,VBScript等)不支持[out]参数。自动化将静默处理任何[out]参数,就好像它是[in, out]一样,这使您处于一个尴尬的位置:客户端应用程序中放置在参数中的任何值都将被泄露,而你的方法无能为力。

如果您计划自动客户端使用您的对象,请不要使用[out]参数。请改用[in, out],并确保在调用之前检查调用者是否在参数上放置了值。代理/存根将始终为[in, out]参数两种方式编组值。如果调用者在调用之前在参数上放置了一个值,则您的方法负责在写入参数之前释放该值。

编辑:扩展指针本身为NULL:

您可以考虑检查NULL并返回E_INVALIDARG如果它为NULL,但我不推荐它。

将NULL作为[out]参数的指针值传递是非法的。即使您的代码处理NULL值,如果调用被编组,编组器也会遇到访问冲突。编组程序必须在返回的路上访问指向的值(以便在其上存储编组的输出),并且它将在不检查null的情况下执行此操作。

在您的特定场景中(调用语义是在给定的情况下没有任何内容可以返回),正确的过程是让调用者始终提供指向存储的指针,并且被调用的方法将值设置为NULL 。像这样:

// Caller
BSTR comment;
hr = obj->a_method( 42, &comment);

// Callee
HRESULT a_method( value, BSTR *comment )
{
    if (...)
    {
        //... I've decided we don't need to return a comment
        *comment = NULL;
    }
    ...
}

如果你真的想拥有你提到的纯空指针语义,你可以;但您必须使用[ptr]属性标记参数。据我所知,这对自动化客户端来说效果不佳,你必须使用自定义编组器。如果您没有预料到会使用自动化客户端,这显然是一种选择。