質問

次のコードブロックがあります。

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を適切に選択する必要があります。

他のヒント

絶対。それ 一度もない 自動的にリリースされ、管理されていないメモリです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top