Marshal.Freehglobalは最終的にブロックに配置する必要があります。
-
29-09-2019 - |
質問
次のコードブロックがあります。
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
Marshal.FreeHGlobal(unmanagedPointer);
ブロックを試してみて、FreeHglobalコマンドを最終的にブロックに配置する必要があります。 (中央のコマンドが例外をスローする場合)。
この場合、最終的にメモリの漏れを防ぐことは理にかなっているようですが、オンラインで見つけた例からは、最終的には使用されません。おそらく、リソースはとにかく自動的に処分されます(それらが管理されていませんが)。
解決
Marshal.Allochglobalに割り当てられた管理されていないメモリは自動的にリリースされません。
したがって、Marshal.freehglobalをaに置きます finally
ブロックは確かに良い考えです:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
try
{
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
}
finally
{
Marshal.FreeHGlobal(unmanagedPointer);
}
あなたが見つけた例は、おそらく簡潔さのためにエラー処理を省略します。
長期的な目的で管理されていないメモリを割り当てている場合(つまり、同じ方法内でそれを解放しない)、派生したオブジェクトにポインターを包むことに興味があるかもしれません safehandle (そのような SafeBuffer).
safehandle 特にパターンを実装するため、オブジェクトを処分するとき、またはガベージコレクターがオブジェクトを収集するときに、管理されていないメモリが解放されます。 SafeHandleはまた、CriticalFinalizerObjectクラスに由来します。これは、メモリが本当に解放されるようにCLRから特別な治療を受けることを意味します。
class HGlobal : SafeBuffer
{
public HGlobal(int cb)
: base(true)
{
this.SetHandle(Marshal.AllocHGlobal(cb));
this.Initialize((ulong)cb);
}
protected override bool ReleaseHandle()
{
Marshal.FreeHGlobal(this.handle);
return true;
}
}
例:
using (var h = new HGlobal(buffer.Length))
{
h.WriteArray(0, buffer, 0, buffer.Length);
}
注:SafeBufferは非常に獣ですので、注意が払われています。
注2:SafeHandlesはP/Invokeでうまく機能し、INTPTRを完全に通過する必要性を排除します。
SafeBuffersは、C#から管理されていないメモリを安全に操作するためであるため、あなたがしていること(P/Invokeで使用するために管理されていないメモリを割り当てるか、C#から管理されていないメモリを操作する)に応じて、SafeHandleまたはSafeBufferを適切に選択する必要があります。
他のヒント
絶対。それ 一度もない 自動的にリリースされ、管理されていないメモリです。