我正在开发一个应用程序,它通过 C++/CLR 包装器涉及本机 C++ 到 C# 互操作。
我在执行以下操作时遇到问题,这会导致内存泄漏:
MyObject data = (MyObject)Marshal.PtrToStructure(ptr, typeof(MyObject));
Marshal.StructureToPtr(data, ptr, false);
(注意:我意识到此时我实际上并没有对“数据”做任何事情,所以这是多余的。)
内存使用量持续上升,直到应用程序因系统内存不足而崩溃。当我删除此代码时,这不会发生。它不是垃圾收集器,因为 a) 它应该在系统内存不足时收集,b) 我尝试使用 GC.Collect() 强制它。
事实上,我已将泄漏范围缩小到 StructureToPtr 命令。
我无法将第三个参数设置为“true”,因为内存是由本机 C++ 分配的,而 C# 认为这个“受保护”的内存无法释放。
我检查了填充的 Data 结构是否完好无损,具有有效数据,并且与等效的本机结构大小相同。
在我看来,这就是应该发生的事情:
我的 ptr 引用的本机结构被编组并复制到“数据”托管结构中
管理结构被复制回 ptr 引用的同一内存。
我看不出这如何导致内存泄漏,因为它的结构大小完全相同,被复制回相同的内存空间。但显然确实如此,删除代码会堵塞泄漏。
这里有一些我不正确理解的机械师吗?
编辑:根据要求,这里是“MyObject”的声明。
C#:
[StructLayout(LayoutKind.Sequential)]
public struct MyObject
{
[MarshalAs(UnmanagedType.I1)]
public bool ParamOne;
[MarshalAs(UnmanagedType.I1)]
public bool ParamTwo;
[MarshalAs(UnmanagedType.I1)]
public bool ParamThree;
[MarshalAs(UnmanagedType.I1)]
public bool ParamFour;
[MarshalAs(UnmanagedType.I1)]
public bool ParamFive;
[MarshalAs(UnmanagedType.I1)]
public bool ParamSix;
[MarshalAs(UnmanagedType.R4)]
public float ParamSeven;
[MarshalAs(UnmanagedType.R4)]
public float ParamEight;
[MarshalAs(UnmanagedType.R4)]
public float ParamNine;
public Vector2f ParamTen;
public Vector2f ParamEleven;
[MarshalAs(UnmanagedType.LPWStr)]
public string ParamTwelve;
[MarshalAs(UnmanagedType.LPWStr)]
public string ParamThirteen;
[MarshalAs(UnmanagedType.LPWStr)]
public string ParamFourteen;
public IntPtr ParamFifteen;
public IntPtr ParamSixteen;
}
C++:
struct MyObject
{
public:
bool ParamOne;
bool ParamTwo;
bool ParamThree;
bool ParamFour;
bool ParamFive;
bool ParamSix;
float ParamSeven;
float ParamEight;
float ParamNine;
Vector2f ParamTen;
Vector2f ParamEleven;
wchar_t * ParamTwelve;
wchar_t * ParamThirteen;
wchar_t * ParamFourteen;
void * ParamFifteen;
void * ParamSixteen;
};
Vector2f的定义如下:
[StructLayout(LayoutKind.Sequential)]
public struct Vector2f
{
[MarshalAs(UnmanagedType.R4)]
float x;
[MarshalAs(UnmanagedType.R4)]
float y;
}