如何防止相同的非托管指针被封装在两个不同的 SafeHandles 中?
Posted
技术标签:
【中文标题】如何防止相同的非托管指针被封装在两个不同的 SafeHandles 中?【英文标题】:How can I prevent the same unmanaged pointer from being encapsulated in two different SafeHandles? 【发布时间】:2018-01-23 00:55:08 【问题描述】:我正在为一个用 C 语言编写的游戏引擎编写一个托管包装器来挑战自己。我已经开始将非托管指针包装在SafeHandle
派生类中,但我认为调用可能返回相同指针的非托管函数可能会创建新的 SafeHandles,如果其中一个被释放,其余的将变为无效。
我怎样才能有效地防止这种情况发生?我怀疑编组器会自动跟踪重复项...
【问题讨论】:
你将如何在非托管代码中解决这个问题?在我看来,如果图书馆按照您的要求行事,那么它将无法使用。我宁愿怀疑您正在创建一个不存在的问题。 我不确定你的意思。在 C 程序中传递指针是正常的,不是吗?我只是想确保我检索到的每个指针都与一个 SafeHandle 类相关联,因此我不会实例化所有指向同一个非托管内存的唯一 SafeHandle 实例。 【参考方案1】:您正在尝试解决大多数托管指针和非垃圾收集技术试图解决的问题。根据用例,有多种解决方案 -
您可以使用引用计数 - 您基本上维护持有特定指针和重载(在 C 中使用函数调用而不是赋值)运算符的句柄数来更新赋值计数。然后,只有在计数达到0
后才释放指针。这种方法虽然准确,但开销很大,而且容易受到循环的影响,因此可能会泄漏内存。这是一个引用计数所有权模型。
您可以创建一个unique_ptr
。这基本上意味着在任何时候只有 1 个句柄持有对特定指针的引用。这意味着如果你做类似的事情 -
a = b
指针将从b
复制到a
和b
将自动失效(更多的是API 的合同,而不是实现)。这意味着用户必须围绕这些约束构建代码。当任何持有引用的对象超出范围时,这里就完成了释放。这是一种独占所有权模式。
还有其他方法(例如weak_ptr
),您可以在任何 C++ 参考资料中了解它们。
【讨论】:
我正在尝试处理托管 (C#) 方面的事情。这些听起来就像您在非托管 (C/C++) 端所做的。当我在 C# 中使用 P/Invoke 编组对 C 函数的调用时,我将IntPtr
s 编组为 SafeHandle
s,这意味着 marhsaller 将指针包装在一个对象中,因为它会自动返回。我要做的是减少 marhsaller 创建的 duplicate SafeHandle
对象的数量。【参考方案2】:
虽然这个答案是针对another question,但在这种情况下它会起作用。
我可以为我创建一个调用托管函数的工厂类,然后像 marhsaller 一样在 Constrained Execution Region 中手动创建 SafeHandles。这个工厂类可以跟踪非托管指针,如果已经创建了 SafeHandle,则返回它而不是创建新指针。
【讨论】:
致对我投反对票的人:这个答案有什么问题?以上是关于如何防止相同的非托管指针被封装在两个不同的 SafeHandles 中?的主要内容,如果未能解决你的问题,请参考以下文章