c# - 使用 MarshalAs(UnmanagedType.LPWStr) 会清理内存吗?

标签 c# pinvoke marshalling

我正在尝试为 ITaskTrigger::GetTriggerString 方法(在 http://msdn.microsoft.com/en-us/library/windows/desktop/aa381866(v=vs.85).aspx 定义)编写一个 pinvoke。如果您查看该页面,它表示该方法的调用者负责释放通过第一个参数引用的 LPWSTR 的内存(通过 CoTaskMemFree)。虽然我可以在 .NET 中手动执行此操作,或者可以使用 ICustomMarshaler 编写我的自定义编码(marshal)拆收器,但我想知道为该特定参数使用 MarshalAs(UnmanagedType.LPWStr) 属性是否会适本地释放内存。

谁能提供一些见解?

最佳答案

首先要注意的是:您在这里谈论的是 COM Interop(ITaskTrigger 是一个 COM 接口(interface)),而不是 P/Invoke。两者有不同的互操作规则,因此保持它们的正确性很重要。例如,您需要为整个接口(interface)定义 C# 互操作包装器,而不仅仅是您想要的方法。这些应该可以帮助您入门:pinvoke.net

简短的回答是,您很幸运,因为 CLR 应该会为您妥善处理这些事情。

较长的答案涉及 COM 互操作代码执行的不同类型的编码,具体取决于参数类型、方向以及您添加到互操作签名的属性。

在这种情况下,您将在调用中获得的参数类型是“out string”参数,具有 MarshalAs(UnmanagedType.LPWSTR) 属性。当 COM 服务器公开具有 LPWSTR 字符串类型的“out”参数的调用时,假设服务器保持其交易结束,它将使用 CoTaskMemAlloc( ) 并将其返回给您。 (如果是不同的字符串类型,比如 BSTR,具体的内存分配调用可能不同,但基本概念是一样的。)此时,你负责清理那 block 内存当您不再需要它时,使用匹配的 CoTaskMemFree() 调用。

这是一种特殊类型的操作,称为“引用更改”:您发送的参数已经是引用参数,但 COM 服务器将替换它为不同的引用。 this MSDN magazine article 的“内存所有权”部分对此过程有很好的解释。 .正如您从那篇文章中看到的那样,当 CLR 从引用类型的“out”参数接收回数据时,它会识别它负责释放该内存。在将该回调编码(marshal)到托管代码时,它使用 MarshalAs 属性来确定这是 COM 中的 LPWSTR 字符串类型指针,因此它应该已被分配使用 CoTaskMemAlloc()。从数据中创建托管字符串后,它将代表您在原始缓冲区上调用 CoTaskMemFree()。您取回的数据将得到全面管理,您无需处理任何所有权问题。

关于c# - 使用 MarshalAs(UnmanagedType.LPWStr) 会清理内存吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8199050/

相关文章:

c# - C# 中的字符数组编码(marshal)处理

c# - MarshalAs 属性案例研究

c# - 从 Javascript 函数调用 AppSettings 中的全局变量

java - HTML 发布请求(登录表单)

c# - 字符串转换,每个单词的第一个字符大写

c# - 字段 'FIELD' 从未分配给,并且始终具有其默认值

c# - 使用 P/Invoke 有什么缺点

c# - 如何调试 C# 托管/非托管编码异常?

java - JAXB - 从 Java 对象字段创建嵌套子元素

c# - 如何使用数据读取器读取字符串值并将其存储在数组中