簡體   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