C++/CLR ラッパーを介したネイティブ C++ から C# への相互運用を含むアプリケーションを開発しています。
次の操作で問題が発生し、メモリ リークが発生します。
MyObject data = (MyObject)Marshal.PtrToStructure(ptr, typeof(MyObject));
Marshal.StructureToPtr(data, ptr, false);
(注:現時点では「データ」に対して実際には何もしていないので、これは不要です。)
システムのメモリ不足によりアプリがクラッシュするまで、メモリ使用量は増加し続けます。このコードを削除すると、これは起こりません。a)システムのメモリが少なくなったときに収集する必要があり、b)GC.Collect()で強制しようとしたため、ガベージコレクターではありません。
実際、リークを StructureToPtr コマンドに絞り込みました。
メモリはネイティブ C++ によって割り当てられ、C# はこの「保護された」メモリを解放できないと見なすため、3 番目のパラメータを「true」に設定できません。
データが取り込まれた 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;
}