何时返回E_POINTER和E_INVALIDARG?

11

COM接口方法可以返回各种HRESULT值,以表示传递的无效参数值。那么什么时候返回 E_POINTER ,什么时候返回 E_INVALIDARG

据我了解,如果一个方法在封装的集合中收到了一个超出边界的索引,则返回 E_INVALIDARG。如果一个方法收到一个Interface**指针,在其中存储指向新创建的对象的指针,则返回E_POINTER

HRESULT CImpl::GetItem( long index; Interface** result )
{
    if( result == 0 ) {
        return E_POINTER;
    }
    if( index < 0 || index >= internalArray.size() ) {
        return E_INVALIDARG;
    }
    *result = CreateWrapperObject( internalArray[index] );
    return S_OK;
}

如果一个方法接收到一个文件名的WCHAR*缓冲区作为“in”参数,但是这个WCHAR*为空呢?这是E_POINTER还是E_INVALIDARG

或者,一个方法接收一个指向某个结构体的指针,并期望通过该指针填充该结构体,但是这个指针为空-这是E_POINTER还是E_INVALIDARG

HRESULT CImpl::SaveToFile( WCHAR* fileName )
{
    if( fileName == 0 ) {
       return // what to return here?
    }
    //... do actual work here
}

HRESULT CImpl::GetAttributes( Attributes* to )
{
    if( to == 0 ) {
       return // what to return here?
    }
    attributes->IsCool = getIsCool();
    attributes->Color = RGB( 0, 255, 0 );
    return S_OK;
}

在检查指针类型参数时,何时返回E_POINTER和何时返回E_INVALIDARG有什么规则吗?

1个回答

12

当一个输出(out)参数的指针引用为空时,应返回E_POINTER,这被认为是程序或互操作层中的错误代码。

如果参数存在范围问题或相互冲突的情况,则应返回E_INVALIDARG

在您的情况下,在SaveToFile(...)中,由于传递空文件名不合法,应返回E_INVALIDARG,而在GetAttributes(...)中,如果它是输出参数,则应返回E_POINTER,因为您无法填充该值。

是的,我们都喜欢 COM :)


你有任何文档参考吗? - Constantin
同意。我真的很想看到关于此的MSDN参考文档。上面的内容有些意义,但最好有权威定义。 - Tom Kirby-Green
我不确定这个答案是否正确。例如,在VS2010的<atlcomcli.h>中,在AtlSetChildSite()实现中,如果punkChild参数为NULL,则返回E_POINTER,而根据这个答案(如果我理解正确的话),应该返回E_INVALIDARG。我认为ATL是良好COM编程实践的良好来源,因此在无效(例如NULL)指针的一般情况下,可能应该返回E_POINTER。但坦率地说,我也不确定,我同意一些MSDN官方参考资料会很好。 - Mr.C64
为了增加混淆,在同一个 <atlcomcli.h> 头文件中,在 CComPtr<IDispatch> 特化中,在 PutProperty() 实现体中,如果 _In_ VARIANT*pVarNULL,则返回 E_POINTER,但如果 _In_ IDispatch*pNULL,则返回 E_INVALIDARG - Mr.C64
我也在想,我在 MSDN 上找到的最接近的答案是:https://msdn.microsoft.com/zh-cn/library/windows/desktop/ff485842(v=vs.85).aspx。由于 out 参数/retval 需要一个有效的指针来“返回”值,所以在没有 COM 的严格规则的情况下,似乎 Shay 是对的。 - Heath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接