是否应该将 Marshal.FreeHGlobal 放置在finally 块中以确保资源得到释放?
我有以下代码块:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
Marshal.FreeHGlobal(unmanagedPointer);
应该将该块包装在 try 中,并将 FreeHGlobal 命令放置在 finally 块中。 (以防中间命令抛出异常)。
在这种情况下,finally 可以防止内存泄漏,这似乎是有道理的,但是从我在网上找到的示例来看,finally 没有被使用。也许资源无论如何都会被自动处置(即使它们不受管理)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用 Marshal.AllocHGlobal 分配的非托管内存不会自动释放。
因此,将 Marshal.FreeHGlobal 放在
finally
块中确实是一个好主意:为了简洁起见,您发现的示例可能省略了错误处理。
如果您要出于长期目的分配非托管内存(即不在同一方法中释放它),您可能有兴趣将指针包装在派生自 SafeHandle(例如 SafeBuffer)。
SafeHandle 实现 IDisposable 模式,因此非托管当您处置对象或垃圾收集器收集对象时,内存将被释放。 SafeHandle 还派生自 CriticalFinalizerObject 类,这意味着它将得到 CLR 的特殊处理,以确保内存真正被释放。
示例:
注意:SafeBuffer 相当猛烈,因此建议小心谨慎。
注 2:SafeHandles 与 P/Invoke 配合良好,并且完全不需要传递 IntPtr。
SafeBuffers 用于安全地从 C# 操作非托管内存,因此根据您正在执行的操作(分配非托管内存以与 P/Invoke 一起使用,或从 C# 操作非托管内存),您应该适当选择 SafeHandle 或 SafeBuffer 作为基类。
Unmanaged memory allocated with Marshal.AllocHGlobal is not automatically released.
So putting Marshal.FreeHGlobal in a
finally
block is indeed a good idea:The examples you've found probably omit error handling for brevity.
If you're allocating unmanaged memory for long-term purposes (i.e. not freeing it within the same method), you might be interested in wrapping the pointer in an object that derives from SafeHandle (such as SafeBuffer).
SafeHandle implements the IDisposable pattern, so the unmanaged memory will be freed when you dispose the object or when the garbage collector collects the object. SafeHandle also derives from the CriticalFinalizerObject class which means it will get special treatment from the CLR to make sure the memory is really freed.
Example:
Note: SafeBuffer is quite a beast, so caution is advised.
Note 2: SafeHandles work well with P/Invoke and eliminate the need to pass around IntPtrs entirely.
SafeBuffers are for safely manipulating unmanaged memory from C#, so depending on what you're doing (allocating unmanaged memory for use with P/Invoke, or manipulating unmanaged memory from C#) you should choose SafeHandle or SafeBuffer as base class appropriately.
绝对地。它永远不会自动释放,它是非托管内存。
Absolutely. It never gets released automatically, it is unmanaged memory.