1

根据MSDN

对于[out]参数,方法或属性分配内存,调用者负责释放内存。

以下哪些是可以的:

[...]
STDMETHOD(Method)([out] BSTR* psValue)
[...]

BSTR myBStr1;
Method(&myBStr1);
::SysFreeString(myBStr1);

BSTR myBStr2 = SysAllocString(L"MyStringValue");
Method(&myBStr2);
::SysFreeString(myBStr2);

BSTR myBStr3 = NULL;
Method(&myBStr3);
::SysFreeString(myBStr3);
4

2 回答 2

4

Yes, garbage is acceptable. The method is responsible to initialize the value. The caller is only responsible for freeing.

MSDN on out attribute:

An [out]-only parameter is assumed to be undefined when the remote procedure is called and memory for the object is allocated by the server.

#1, #3 are OK. #2 is going to create a memory leak.

This rule is actually creating some confusion. If a method returns an error, you might be not sure whether the values are already initialized or not. If you attempt to release garbage, it is going to give an access violation or corrupt memory. If you skip memory freeing and partially successful method left something meaningful there (well, it is the problem on server side but still), then you leak memory. It is certainly safer to initialize with NULL before the call, and CComBSTR constructor, for instance, would do it for you. On server side, you might want to start your method with NULL initialization of [out] values to not accidentally leave them uninitialized later.

于 2013-06-07T11:31:54.920 回答
3

从编组调用的角度来看规则(即当对象位于不同的 COM 单元时,或者当它位于不同的进程或机器中时会发生什么);您将了解规则是如何运作的,以及为什么它是唯一合理的规则。

关键事实是,对于[out]参数,编组器不会将初始值编组给被调用者。

这意味着在进行调用之前您在变量中输入的内容并不重要。它可以是垃圾或NULL。没有人会看它。

注意:这也意味着如果变量在调用之前包含需要释放的东西,你必须在调用之前自己释放它,否则会泄漏。编组器不会为您释放它(因为作为参数[out],编组器必须假定它是垃圾)并且被调用者即使想要也无法释放它(因为它永远不会从编组器获得现有值)。

第二,调用返回后,被调用者无法知道你对返回值做了什么,所以唯一能释放参数的,就是调用者。

有错误条件的情况有点危险。

原则上,COM 要求[out]在返回之前必须将参数设置为一致的(“marshallable”?)值(NULL 或等效值,或有效值),即使存在错误也是如此。这也是“唯一明智的规则”:编组器无法知道被调用者处于错误情况。它也不会根据 HRESULT 进行猜测,因为即使是“错误类”HRESULT 也不意味着该方法不打算将值返回给调用者。编组器会将参数的值编组回调用者 - 错误或无错误 - 所以参数最好是有效的,否则编组器本身会崩溃。

在实践中……嗯,有些对象比其他对象写得更好,有些 COM 类从不通过编组调用,因此类的开发人员永远不会发现问题。不符合这些规则的类不能在公寓间安全使用。

即使面对错误情况,确保参数值保持一致的规范方法如下所示:

STDMETHODIMP Class::Method(BSTR *pValue)
{
  *pValue = NULL;        // 1) Initialize all the [out] parameters before
                         //    doing anything, to make sure they are always
                         //    consistent

  BSTR tempValue;        // 2) Use a temporary to hold any result value

  ...                    // 3) Use the temporary for all computations
  ...                    //    Finish all other processing

  *pValue = tempValue;   // 4) Only after all possible error conditions
                         //    are behind us, do put the new value
                         //    in the output parameter

  return S_OK;
}

显然,如果 out 参数只是一个不需要释放的值(如 int 等),那么这些都不重要。

于 2013-06-07T13:48:15.430 回答