IntPtr、SafeHandle 和 HandleRef - 解释
Posted
技术标签:
【中文标题】IntPtr、SafeHandle 和 HandleRef - 解释【英文标题】:IntPtr, SafeHandle and HandleRef - Explained 【发布时间】:2010-10-06 07:32:59 【问题描述】:如果不将我指向 MSDN,有人可以简明扼要地解释每一个的目的以及何时使用它们。 (IntPtr、SafeHandle 和 HandleRef)
【问题讨论】:
没什么。只是寻找每个的简短摘要,以确保我正确使用它们。如果我阅读 MSDN 和其他人的描述,我会更好地了解我所做的是否正确。 【参考方案1】:IntPtr
只是一个简单的基于整数的结构,可以保存一个指针(即,在 32 位系统上为 32 位大小,在 64 位系统上为 64 位大小)。
SafeHandle
是一个用于保存 Win32 对象句柄的类 - 它有一个终结器,可确保在对象被 GC 时关闭句柄。 SafeHandle
是一个抽象类,因为不同的 Win32 句柄有不同的关闭方式。在引入SafeHandle
之前,IntPtr
用于保存 Win32 句柄,但确保它们被正确关闭并防止被 GC 是程序员的责任。
HandleRef
是一种确保在 P/Invoke 调用过程中未对非托管句柄进行 GC 的方法。如果没有HandleRef
之类的东西,如果您的托管代码在 P/Invoke 调用之后对句柄没有做任何事情,如果在 P/Invoke 调用期间运行 GC,它不会意识到句柄仍在使用中,并且可能GC它。我想(但我不确定也没有看过)SafeHandle
可能会使用HandleRef
作为其封装句柄管理的一部分。
【讨论】:
小幅修正。当您不希望在 PInvoke 期间对 托管 对象进行 GC 时,请使用 HandleRef。例如 class HWnd public IntPtr Handle; HWnd a = 新 HWnd(); B.SendMessage(a.Handle, ...); 另一个补充:SafeHandle
包括引用计数以防止句柄回收攻击。
谁能确认safehandle使用handleref?或者至少有类似的机制?
@Assimilater 是的:机制类似。 HandleRef 和 SafeHandle 都受到 GC 保护,直到调用返回;并且两者都保护对象的终结器不运行和删除 IntPtr。 HandleRef 指向带有终结器的对象;而 SafeHandle 是具有该终结器的对象。
考虑到这三个的结构,IntPtr
不能与SafeHandle
或SafeRef
交换,因为Safe*
类型都不是仅32/64 位,对吧?【参考方案2】:
HWnd a = new HWnd();
B.SendMessage(a.Handle, ...);
假设这是程序中对“a”的唯一引用,这相当于:
HWnd a = new HWnd();
IntPtr h = a.Handle;
// a is no longer needed and thus can be GC'ed
B.SendMessage(h, ...);
问题是当“a”被释放时,它会关闭句柄。如果在调用 SendMessage 之前或期间发生这种情况,则句柄将无效。
HandleRef 防止在程序使用 h 完成之前对“a”进行垃圾回收。
【讨论】:
以上是关于IntPtr、SafeHandle 和 HandleRef - 解释的主要内容,如果未能解决你的问题,请参考以下文章
无法将 ReleaseHandle 中的 SafeHandle 实例传递给本机方法
SafeHandle 中 invalidHandleValue 的作用是啥?