场景
C++/CLI主要用于对c++编译的dll进行封装,方便.net调用。既然说到C++,难免dll中会有多处使用到指针,比较常见的就是外部传入一个List<string>
,需要在CLI中转化成char**,然后才能调用对应的c++方法。作为中间变量,这些被我们临时生成的指针需要手动释放。简单场景代码如下:
array<String^>^ list;//500个字符串
int count = list->Length;
char** arrays = new char*[count];
for (int i = 0; i < count; i++)
{
arrays[i] = (char*)(void*)Marshal::StringToHGlobalAnsi(list[i]);
}
// use arrays in C++ function
//free memory
for (int i = 0; i < count; i++)
{
delete arrays[i];
}
delete[] arrays;
基本上c++的指针释放都是这么操作。但是在C++/CLI中就出现了错误,释放内存时出现溢出。
尝试过只使用delete[] arrays
。能正常运行,但是内存没有被正确释放。
解决方案
char* ptr = (char*)(void*)Marshal::StringToHGlobalAnsi(string)
,这是托管字符串转非托管char
指针的操作。对应的内存释放操作是Marshal::FreeHGlobal(IntPtr(ptr))
- 这个场景下的二维数组
char**
内存释放应该由两部分组成。释放成员指针,再释放数组指针。
for (int i = 0; i < count; i++)
{
Marshal::FreeHGlobal(IntPtr(arrays[i]));
}
delete[] arrays;
- 经10万次循环测试,没有出现内存溢出。而原方法在循环几百次后,内存已经泄露了100MB以上。
相关参考:
- https://m.imooc.com/article/30475
- https://stackoverflow.com/questions/6754415/free-delete-a-char-causes-an-invalid-heap-pointer-assertion-failure
- https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.stringtohglobalansi?redirectedfrom=MSDN&view=netcore-3.1#System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi_System_String_