字符串编组和内存管理

String marshalling and memory management

假设我在库中导出了以下 C++ 函数:

void foo(const wchar_t* text);

和使用该函数的 C# 代码:

[DllImport("bla.dll")]
static extern void foo([MarshalAs(UnmanagedType.LPWStr)] string text);

void Bar()
{
    string s = "hello";
    foo(s);
}
  1. 当我调用 foo 时,.net 编组器是否复制字符串,或者指针是否指向 s 的缓冲区?
  2. 如果值被复制,什么时候清理?
  3. 我必须自己清理它吗(大概在 foo 里面)?
  4. 如果是,如何清理内存?

如果 text 编组为:

,会有什么行为?
  1. UnmanagedType.LPWStr
  2. UnmanagedType.BStr
  1. Does the .net marshaller copy the string when I call foo or does the pointer point to the buffer of s?

LPWSTR 按值传递的特定情况意味着托管字符串被固定并由本机代码直接使用,see here. In all other cases, the string is copied, see here

  1. If the value is copied, when is it cleaned up?

编组器在函数调用后进行任何释放 returns。

What's the behavior if text is marshalled as:

  1. UnmanagedType.LPWStr
  2. UnmanagedType.BStr

最终行为是相同的,因为传递给本机函数的指针在函数调用后无效 returns。在 LPWStr 的情况下,它将指向与托管字符串使用的相同内存(可能在本机函数 returns 之后移动),对于 BStr,它将指向由编组器分配的临时缓冲区(它将在本机函数 returns).

后被释放

如果您需要本机函数来获取指针的所有权,您需要传入一个 IntPtr,它指向您以合适的方式分配给自己的一些内存(可能通过调用一些本机代码,可能通过使用 AllocHGlobal 等)。指针将需要由您或使用相同机制的本机代码手动释放。