繁体   English   中英

C#清理C ++分配的内存吗?

[英]Does C# clean up C++ allocated memory?

我有一个带有以下签名的假设COM对象

void MemAlloc(ref double[] test, int membercount)

使用new / malloc在C ++中分配内存的地方。 一旦这是在C#中,使用RCW,我如何确保正确释放内存? 我认为.NET很难释放,考虑到在C ++中你需要知道它是否已经分配了new / malloc / mm_malloc才能正确释放它。 那么,清理我的C ++分配数组的合适方法是什么? 谢谢。

我相信您应该将CoTaskMemAlloc()用于您希望从托管端明确释放的内存。 一旦不再可用,CLR将负责释放内存。 如果要明确释放它,可以使用托管的Marshal.CoTaskFree()例程。

一般来说,interop marshaler和CLR遵守COM约定来释放内存; 收件人负责释放记忆。 因此,如果将内存返回给托管调用方,CLR / Interop封送程序通常会处理释放本机调用中分配的内存。

使用Interop Marshaler (msdn)进行内存管理

interop marshaler总是尝试释放由非托管代码分配的内存。 此行为符合COM内存管理规则,但不同于管理本机C ++的规则。

如果您在使用平台调用时预期本机C ++行为(无内存释放)会产生混淆,平台调用会自动释放指针的内存。 例如,从C ++ DLL调用以下非托管方法不会自动释放任何内存。

运行时始终使用CoTaskMemFree方法释放内存。 如果您使用的内存未使用CoTaskMemAlloc方法分配,则必须使用IntPtr并使用适当的方法手动释放内存。

将其包装在实现IDisposable的对象中,并确保C#包装器被释放。

这是我写的关于实现IDisposable的简单方法的博客

我几乎100%确定CLR不会自动释放分配用于测试的内存(如果它是PInvoke我会100%肯定)。 原因是,CLR如何知道你用来分配内存的东西? 即它没有。

编写此函数的更安全的方法如下

void MemAlloc(ref IntPtr arrayPtr, int membercount)

收到回电后,您可以执行以下操作。

var count = GetTheCount();
var arrayPtr = IntPtr.Zero;
obj.MemAlloc(ref arrayPtr, count);
byte[] test = MarshalThePtrToByteArray(arrayPtr, count);
Marshal.FreeCoTaskMem(arrayPtr);

这是MarashalThePtrToByteArray的快速而又脏的实现

byte[] MarashalThePtrToByteArray(IntPtr ptr, int count) {
  byte[] arr = new byte[count];
  for ( int i = 0; i < count; i++ ) {
    arr[i] = (byte)Marshal.PtrToStructure(ptr, typeof(byte));
    ptr = new IntPtr(IntPtr.ToInt64() + Marshal.SizeOf(typeof(byte)));
  }
  return arr;
}

.NET 2.0 Interoperbility Recipes这本书看起来很方便。 这似乎与Arnshea关于CoTaskMemFree的内容一致。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM