.NET中SafeBuffer和SafeHandleZeroOrMinusOneIsInvalid有哪些主要区别?

3

主要区别在哪里?我知道SafeBuffer派生自SafeHandleZeroOrMinusOneIsInvalid,还有什么区别吗?

什么情况下应该使用其中之一?

我需要分配和控制本地数组(在CPU或GPU上)。我的托管自定义数组应该实现SafeBuffer还是SafeHandleZeroOrMinusOneIsInvalid?SafeBuffer听起来更合理,但为什么我要实现它并在使用之前调用Initialize?

1个回答

3
主要区别在哪里?
它们几乎没有任何共同点。SaveBuffer继承自SafeHandle以利用SafeHandle提供的关键终结器。这确保即使在最极端的情况下,如程序中的硬崩溃会阻止终结器执行的情况下,缓冲区也会被释放。
SaveBuffer是未受管理的内存的包装器,该内存是通过操作系统调用获得的。它只有一个仍然是抽象的方法ReleaseHandle()。因为不同的winapi调用有不同的方式来释放与内存相关联的句柄。例如,LocalAlloc()需要LocalFree()。SysAllocString()需要SysFreeString()。MapViewOfFile()需要UnmapViewOfFile()等等。
您可以从SaveBuffer()派生自己的类,以利用安全句柄的保证。它需要一个构造函数,该构造函数获取未受管理的指针并调用SetHandle()。它还需要实现ReleaseHandle()以再次释放内存。
是否应该这样做是非常值得怀疑的。ReleaseHandle()方法由关键终结器调用。在这样的方法中,有许多您无法执行的操作,要求关键终结器本身不会引起任何损坏,这将阻止其他关键终结器运行。CLR运行在防止生成异常的模式下,例如。它只在自定义CLR托管环境中真正重要,该托管环境提供了强大的保证以获取最长的正常运行时间,SQL Server是主要例子。如果您进行操作系统调用,则可以使用它,这是坚如磐石的代码。GPU缓冲区,那不怎么样。如果释放调用失败,则通过创建自己的包装器及其自己的终结器,您可能会更加容易地调试故障。

3
我还是不理解。SafeBuffer 继承自 SafeHandleZeroOrMinusOneIsInvalid,包括抽象的 ReleaseHandle()。你所说的也适用于 SafeHandle,对吗?我不理解的是 SafeBuffer 多出来的东西,以及为什么我们需要在使用 SafeBuffer 实例之前调用 Initialize(而在使用 SafeHandleZeroOrMinusOneIsInvalid 实例时则不需要)。要控制本机数组,我只需使用 SafeHandleZeroOrMinusOneIsInvalid,其中 handle = IntPtr(malloc(...)),对吗? - zer0ne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接