gpt4 book ai didi

memory-management - 内存管理

转载 作者:行者123 更新时间:2023-12-02 00:30:19 25 4
gpt4 key购买 nike

我有一些关于 COM 内存管理的问题:

  1. 我有一个 COM 方法:

    STDMETHODIMP CWhitelistPolicy::GetWebsitesStrings(SAFEARRAY** 结果)

结果 = SAFEARRAY(BSTR)。如果我从另一个接口(interface)方法接收到另一个 SAFEARRAY(BSTR)(为了设置 *result),我是否必须复制接收到的字符串以便将它们传递给 *result 和外部客户端?或者考虑到我不会自己使用这些字符串,我可以将它们传递给客户(并传递所有权)?

2.

STDMETHODIMP CWhitelistPolicy::SetWebsitesStrings(SAFEARRAY* input)

这里我收到一个 BSTR 数组作为输入。同样,我的方法负责输入中分配的内存?

3.

STDMETHOD(SetUsers)(SAFEARRAY* input);

在这里,我在另一个接口(interface) (SetUsers) 上调用一个方法,并为输入 SAFEARRAY 分配内存。在我调用 SetUsers 之后我可以处理 SAFEARRAY 吗?当编码发生时,内存总是被复制,不是吗? (在我的例子中,SetUsers 方法是在我的进程中作为 COM DLL 托管的接口(interface)上调用的)

最佳答案

我考虑回答此类问题的方式是考虑跨机器的 COM 调用。那么 [out] 参数就很明显了;我调用者拥有并且必须释放内存,因为远程编码(marshal)处理层无法做到这一点。对于 [in] 参数,很明显编码层必须复制我的数据,而且远程编码层也无法释放我传入的数据。

COM 的核心原则是位置中立性,在同一间公寓内调用时的规则就是跨机器使用 DCOM 时的规则。

  1. 您有责任释放 - 当您调用下一个 fnc 时您不会传递所有权,因为它可能是远程的并且获取副本,而不是您的原始数据。

  2. 不 - 作为被调用者,您不必释放它。如果它是公寓内的,它是调用者提供的内存,调用者必须释放它。如果是远程调用,服务器 stub 会分配它并在方法返回时释放它。

  3. 是的,您释放它 - 不,它并不总是被复制(可能是),这就是为什么对 2 的回答是否定的。如果它被复制,就会有一个已分配的 stub , stub 将释放它。

请注意,我对您问题的回答并未涵盖 [in,out] 参数的情况 - 请参阅 so 问题 Who owns returned BSTR?有关此案例的更多详细信息。

Com allocation rules复杂但理性。如果您想了解/查看所有案例的示例,请获取 Don Box 的书“essential com”。你仍然会犯错误,所以你应该有一个检测它们的策略。我使用 gflags(Windbg 的一部分)及其堆检查标志来捕获双重释放(显示调试消息并在使用 INT 3 的调用时停止执行)。 Vstudio 的调试器过去常常在启动可执行文件时为您打开它们(现在可能仍然如此),但您可以使用图像选项选项卡下的 gflags 强制打开它们。

您还应该知道如何使用 UMDH (也是 windbg 的一部分)来检测泄漏。 DebugDiag是较新的工具,似乎更易于使用,但遗憾的是,您只能安装 32 位或 64 位版本,而不能同时安装两者。

那么问题是 BSTR,它被缓存,使得检测双重释放和泄漏变得棘手,因为与堆的交互被延迟了。您可以通过设置环境变量 OANOCACHE 来关闭 ole 字符串缓存。为 1 或调用函数 SetOaNoCache .该函数未在头文件中定义,因此请参阅此 SO 问题 Where is SetOaNoCache defined? .请注意,已接受的答案显示了通过 GetProcAddress() 调用它的困难方法。已接受答案下方的答案显示您所需要的只是一个 extern“C”,因为它位于 oleaut32 导出库中。最后看this Larry Osterman 的博文更详细地描述了缓存在查找泄漏时造成的困难。

关于memory-management - 内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7195797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com