【问题标题】:Can I get the GCHandles for a pinned object from the object?我可以从对象中获取固定对象的 GCHandles 吗?
【发布时间】:2011-05-07 21:47:42
【问题描述】:

我在 .NET 上固定一个对象并获得一个 GCHandle。我想泄露大部分这些 GCHandle 并忘记它们(因此对象继续被固定)。稍后,对于一些对象,我想取消固定它们。那时我只有对象(或对象的地址)。

似乎每个 GCHandle 固定调用都会返回一个新的 GCHandle。 GCHandle.ToIntPtr 和 GCHandle.FromIntPtr 表明本机 int 等效于这些 GCHandles。

是否可以从对象或 AddrOfPinnedObject 中获取 GCHandle(s)?

【问题讨论】:

  • 我正在寻找相同的解决方案。我有一个不再受支持的第三方组件,它似乎在固定我们拥有的对象。我想强制释放该对象,但没有对 GCHandle 的引用。如果您找到任何解决方案,请传递。

标签: c# .net interop


【解决方案1】:

不,一旦你失去了 GCHandle,你就永远失去了它。垃圾收集器中没有“句柄的句柄”的概念。您只能为一个对象创建一个 new GCHandle,它会添加一个额外的引用。这个丢失的句柄引用的对象将被永久引用,这是一个泄漏。注意 GCHandle 是一个结构体类型。

将对象固定在任何时间长度的想法都会损害程序的性能。除了让 GC 更难绕过障碍物之外,它还阻止了它正确压缩堆。这增加了缓存未命中的可能性,这在现代内核上非常昂贵。这些副作用可能会持续一段时间。

如果您需要固定内存,则使用 Marshal.AllocCoTaskMem() 分配它。这也会阻止您创建指向具有不可预测的内存布局的托管数据的指针。不同版本的 JIT 编译器之间的布局不同,并且高度依赖于结构或类声明。只有 Marshal.StructureToPtr() 可以给你硬性保证。

【讨论】:

【解决方案2】:

对于那些你需要释放的,保留 GCHandles 并使用Free。 GCHandle 知道对象,而不是相反。

此外,您希望将对象保持固定也不是很好。我希望你意识到你会阻止 GC 正常工作。

【讨论】:

  • 似乎我们需要维护 GCHandle 表的 ptr 以支持取消固定以响应 ptr 上的“空闲”。
  • 我意识到固定将修复堆中的对象。有没有办法确保它们在大对象堆中?
  • 把它们变大; 128kb 应该可以,但谷歌它。为什么还需要固定大量对象?
  • Google 报告大小是一个调整值,例如85000 字节。 msdn.microsoft.com/en-us/magazine/cc534993.aspxAFAIK,这些对象是缓冲区,要传递到一些预先存在的非托管代码中。
猜你喜欢
  • 2015-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-06
  • 2012-05-31
  • 2020-07-16
  • 1970-01-01
  • 2010-09-29
相关资源
最近更新 更多