2010-11-10 92 views
4

我在.NET上固定一个对象并获得一个GCHandle。我想泄漏大部分这些GCHandle并忘记它们(所以这些对象继续被固定)。后来,我想解锁一些物体。那时我只有对象(或对象的地址)。我可以从对象获取固定对象的GCHandles吗?

看来每个GCHandle固定调用返回一个新的GCHandle。 GCHandle.ToIntPtr和GCHandle.FromIntPtr显示本地整数等于这些GCHandles。

是否有可能从一个对象或从AddrOfPinnedObject获取GCHandle?

+0

我正在寻找相同的解决方案。我有一个不再支持的第三方组件,它似乎是固定我们拥有的对象。我想强制该对象被释放,但没有对GCHandle的引用。如果您发现任何解决方案,请将其传递。 – jpierson 2011-11-16 18:33:59

回答

3

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

保持对象固定任何时间长度的想法都不利于您的程序的性能。由于给了GC更难以解决障碍的问题,它也阻止了它正确压缩堆。这增加了缓存未命中的可能性,在现代内核上非常昂贵。这些副作用可能会持续一段时间。

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

+0

Marshal.AllocCoTaskMem看起来相关。谢谢。 http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.alloccotaskmem.aspx – James 2010-11-10 14:38:22

+0

Marshal.AllocHGlobal在这里http://msdn.microsoft.com/en-us/library/ system.runtime.interopservices.marshal.allochglobal.aspx – James 2010-11-10 15:00:00

+0

Hans有很好的建议http://stackoverflow.com/questions/1887288/marshal-allochglobal-vs-marshal-alloccotaskmem-marshal-sizeof-vs-sizeof/1887765#1887765 – James 2010-11-10 15:00:17

0

对于那些你需要自由,保持GCHandles和使用Free。 GCHandle知道对象而不是其他方式。

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

+0

好像我们需要维护ptr到GCHandle表以支持unp以响应ptr上的“free”。 – James 2010-11-10 14:06:29

+0

我意识到固定会修复堆中的对象。有没有办法确保他们在大型对象堆中? – James 2010-11-10 14:07:02

+0

使它们变大; 128kb应该做的,但谷歌它。为什么你需要固定大量的物体呢? – 2010-11-10 14:26:41

相关问题