com - 我应该强制输出参数为非 NULL 吗?

标签 com

IDL 中的示例方法:

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

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

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

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

最佳答案

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

获取[out]参数的方法永远不应该查看参数的值,直到它在其中添加内容。这是未初始化的内存。垃圾。事实上,如果您的方法是通过编码调用(公寓间或进程间)调用的,则垃圾正是您得到的:您的调用者在调用您的方法时可能放置的任何内容,都会被代理丢弃并忽略 stub ;你永远不会得到它。

如果客户端/调用者在调用你的方法之前在参数上放置了一些东西,那么这绝对是内存泄漏(当然,假设它是像 BSTR 这样的已分配对象),但这是调用者的错误。被调用的方法从来没有责任来处理它。被调用的方法即使想要处理泄漏也无法处理。

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

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

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

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

您可以考虑检查 NULL 并在为 NULL 时返回 E_INVALIDARG,但我不建议这样做。

将 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] 属性来标记参数。据我所知,这对于自动化客户端来说效果不佳,并且您必须使用自定义编码器。如果您不打算使用自动化客户端,这显然是一个选择。

关于com - 我应该强制输出参数为非 NULL 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24520852/

相关文章:

c++ - AfxOleInit 和 OleInitialize 有什么区别?

c++ - 在 COM 对象上调用 Release 似乎永远不会返回

internet-explorer - 有没有办法强制 IE 卸载 ActiveX 控件?

c++ - 将 dll 转换为 COM - C++

c++ - CoCreateInstance 返回 E_NOINTERFACE 即使找到接口(interface)

com - 在哪里可以找到可以在 Powershell 中创建的所有 COM 对象?

c++ - 从存储在 CTreeCtrl 的 LPARAM 中的结构中检索地址/指针 (IXMLDOMNode*) - 不工作

com - ATL::CComModule::RegisterServer

Windows Server 2012 中的 C# 动态 COM

c++ - 要在 Excel 工作表上直接使用 ActiveX 控件,有哪些必要和充分的要求?