Dot-Net

從託管程式碼中釋放非託管記憶體分配

  • March 5, 2021

.NET 應用程序呼叫 C dll。C 程式碼為 char 數組分配記憶體並返回該數組作為結果。.NET 應用程序將此結果作為字元串獲取。

C程式碼:

extern "C" __declspec(dllexport) char* __cdecl Run()
{
   char* result = (char*)malloc(100 * sizeof(char));
   // fill the array with data
   return result;
}

C# 程式碼:

[DllImport("Unmanaged.dll")]
private static extern string Run();

...
string result = Run();
// do something useful with the result and than leave it out of scope

對它的一些測試表明垃圾收集器不會釋放 C 程式碼分配的記憶體。

任何幫助將不勝感激。:)

託管字元串與 char* 不同。秘密發生的是互操作層中的編組程式碼複製非託管字元串以將其轉換為託管字元串,但它無法釋放該記憶體,因為它不知道它是如何分配的。

但是,您可以嘗試分配和返回 BSTR 而不是 char*。與經典的非託管數據類型相比,互操作層更好地處理自動化數據類型。

重要的原因是 char* 和 BSTR 在記憶體中的分配方式。

char* 緩衝區是使用 CLR 不知道的私有分配/釋放常式在 C++ 執行時的堆上分配的,因此它無法刪除該記憶體。更糟糕的是,char* 指向的緩衝區可以由 dll 程式碼的內部堆實現分配,或者它甚至可能指向私有類中的成員變數。

另一方面,BSTR 使用 WIndows API SysAllocString 分配並由 SyFreeStirng 釋放,並且由於 CLR 互操作層知道這些 Windows API,它知道如何釋放從非託管程式碼中獲得的 BSTR。

引用自:https://stackoverflow.com/questions/1932365