非托管结构体MyStruct调用HDF5GetSubGroups时是否内存泄漏?
你的代码会导致内存泄漏,这里是原因和修复方案
先直接给结论:是的,你的代码存在内存泄漏问题,问题出在MyStruct里的IntPtr指向的非托管内存没有被释放。
为什么会泄漏?
- 当你调用
H5A.read把数据读取到MyStruct数组时,其中的intPtr指向的是HDF5库在非托管堆上分配的内存(用来存储字符串的原始字节)。 - 你用
Marshal.PtrToStringAnsi(ipp)把非托管字符串转成了托管的string,这一步只是把字符串内容复制到了托管内存里,但完全不会处理原始的非托管内存。 - 当
myStruct数组被.NET GC回收时,作为值类型的MyStruct和它的IntPtr成员会被清理,但IntPtr指向的那块HDF5分配的非托管内存,因为没有被主动释放,就会一直留在内存里,造成泄漏。
怎么修复?
HDF5库分配的内存必须用它自己的释放函数来清理(不能用Marshal.FreeHGlobal这类通用方法,否则可能导致堆损坏)。你需要调用HDF5提供的H5free_memory对应的.NET封装方法,一般是H5.free_memory。
修改你的代码,确保在读取完字符串后释放内存:
方案1:在字符串转换的方法里自动释放
private string IntPtrToString(IntPtr ipp) { try { // 先把非托管字符串转成托管string return Marshal.PtrToStringAnsi(ipp); } finally { // 不管转换成功与否,都释放HDF5分配的内存 H5.free_memory(ipp); } }
方案2:在外部手动释放
如果你不想在转换方法里处理,也可以在读取完字符串后立即释放:
string myStructVariableString = IntPtrToString(myStruct[0].intPtr); returnList.Add(myStructVariableString); // 释放当前元素的IntPtr指向的非托管内存 H5.free_memory(myStruct[0].intPtr);
额外注意
如果你要遍历整个myStruct数组处理多个元素,每个元素的intPtr都要单独释放,不能只释放第一个,否则其他元素的非托管内存还是会泄漏。
内容的提问来源于stack exchange,提问作者ntmt
相关产品推荐
相关产品推荐

