是否GCHandle.Alloc做任何事情,除了保持一个引用一个对象? [英] Does GCHandle.Alloc do anything beyond keeping a reference to an object?

查看:1867
本文介绍了是否GCHandle.Alloc做任何事情,除了保持一个引用一个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的GCHandle。 ALLOC 免受垃圾收集对象,而只是持有该对象的引用在一个静态变量也将防止它被收集。有什么好处没有 GCHandle.Alloc 提供(假设 GCHandleType.Normal )?

本文说代表们不必固定在任何特定的内存位置,但我找不到任何的MSDN文档来支持这种说法了。如果委托是由CLR垃圾收集感动,怎能umanaged库找到它,这样它可以被称为?

This article says that delegates "need not be fixed at any specific memory location" but I can't find any documentation on MSDN to back that statement up. If the delegate is moved by the CLR garbage collector, how can the umanaged library find it so that it can be called?

注意代表的无法被固定;你会得到一个例外,说明对象包含非基本或非blittable数据。

Note that delegates cannot be pinned; you will get an exception stating "Object contains non-primitive or non-blittable data".

推荐答案

管理对象通常由发现步行的AppDomain静垃圾收集和正在运行的线程和对象,他们在GC堆引用的堆栈。但也有某些情况下,其中的集电极本身不能够找到一个对象,该对象是活,不应该被收集参照的

Managed objects are normally discovered by the garbage collector by walking AppDomain statics and the stacks of the running threads and the objects they reference on the GC heap. But there are certain scenarios where the collector itself is not capable of finding a reference to an object that's live and should not be collected.

此情况发生时,非托管代码使用这样的对象。此代码是不是即时编译使GC有发现后面的对象引用没有什么好办法,这样的代码的堆栈帧不能可靠地进行检查,发现指针回来。你必须确保GC仍然看到了借鉴。这是的GCHandle做什么。它使用CLR内建成GC手柄的专用表。您分配一个进入这个表GCHandle.Alloc(),并再次与后来发布GCHandle.Free是()。该垃圾收集器只是添加条目此表的对象图才发现,自己当它执行的集合

This happens when unmanaged code uses such objects. This code is not jitted so the GC has no good way to discover the object references back, the stack frame of such code cannot reliably be inspected to find the pointer back. You must ensure that the GC still sees a reference. Which is what GCHandle does. It uses a dedicated table of GC handles built inside the CLR. You allocate an entry into this table with GCHandle.Alloc() and release it again later with GCHandle.Free(). The garbage collector simply adds the entries in this table to the graph of objects it discovered itself when it performs a collection.

gcroot<>在C ++ / CLI关键字是例如这一点。它允许编写可以存储一个简单的原始指针并在需要的地方它转换回托管对象引用非托管代码。该GCHandle.ToIntPtr()方法产生的指针,FromIntPtr()恢复对象引用。该的GCHandle表条目确保对象将不会被收集,直到非托管代码明确要求免费()。通常由一个C ++的析构函数完成。

The gcroot<> keyword in C++/CLI is an example of this. It allows writing unmanaged code that can store a simple raw pointer and have it converted back to the managed object reference where needed. The GCHandle.ToIntPtr() method generates that pointer, FromIntPtr() recovers the object reference. The GCHandle table entry ensures the object won't be collected until the unmanaged code explicitly calls Free(). Usually done by a C++ destructor.

的GCHandle还支持引脚对象的能力,当你需要编组为本地代码和PInvoke的编组不能得到使用任务完成。你会传递GCHandle.AddrOfPinnedObject的返回值()。它实现了弱引用,但你通常总是使用的WeakReference类的。它实现异步固定手柄,使固定I / O缓冲区上的I / O完成,这不是直接暴露一个能力将自动被取消固定。所以,是的,确实的GCHandle比只是保持一个参考了。

GCHandle also supports the ability to pin an object, used when you need to marshal to native code and the pinvoke marshaller can't get the job done. You'd pass the return value of GCHandle.AddrOfPinnedObject(). And it implements weak references, although you'd normally always use the WeakReference class for that. And it implements async pinned handles, allowing pinned I/O buffers to be unpinned automatically on an I/O completion, a capability that's not directly exposed. So yes, GCHandle does more than just keeping a reference.

和你有关委托的问题显著的CLR支持使用代理来调用本机代码。底层的辅助函数是Marshal.GetFunctionPointerForDelegate()。它动态地构建一个机器代码存根,允许本地代码回调到托管代码。这需要留引用的委托对象,GCHandle.Alloc()通常用于这一点。这是不是唯一的方式,储存委托到一个静态变量是另一种方式,以确保委托对象不会被垃圾收集。该委托没有,否则必须被固定,一个GCHandleType.Normal是好的。

And significant to your question about delegates, the CLR supports using a delegate to call native code. The underlying helper function is Marshal.GetFunctionPointerForDelegate(). Which dynamically builds a machine code stub that allows native code to callback into managed code. This requires the delegate object to stay referenced, GCHandle.Alloc() is often used for that. It isn't the only way, storing the delegate into a static variable is another way to ensure that the delegate object won't be garbage collected. That delegate doesn't otherwise have to be pinned, a GCHandleType.Normal is fine.

这是使用了很多在任何.NET程序,但大部分是出于人们的视线。特别是在.NET框架代码本身和PInvoke的编组。不必使用的GCHandle保护时,本机代码存储函数指针以后可以回调的委托对象才是必需的。

This is used a lot in any .NET program, but most of it is out of sight. Particularly in the .NET framework code itself and in the pinvoke marshaller. Having to use GCHandle to protect a delegate object is only necessary when the native code stores the function pointer and can make callbacks later.

这篇关于是否GCHandle.Alloc做任何事情,除了保持一个引用一个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆