[作者编辑:] 确实,这似乎与a post from 3 months ago非常相似。虽然这两个问题都包含有用的要点 - 每个问题都有一些独特之处 - 但这个页面还是值得以只读方式存档,因为它提供了稍微不同的视角,不同的示例案例,并且包含一些活泼的内容讨论部分中的讨论和有价值的专家信息。
在 C#7 中使用ref local和ref return,现在可以将托管指针保留在内部无限期地引用类型class
实例。 1。由于内部引用可能是ValueType
,感觉这可能会在某种意义上引入托管指针的可能性孤立,如果主机本身被收集。
这是一个完整且独立的例子。内部和下方的评论继续讨论。
class outer { public int m_i; }; // outer reference type containing a value-type field
static class _
{
// the lone reference to a single global instance of 'outer' in the GC heap
static outer host_inst = new outer();
// (function here for clarity, and to prevent distraction over 'keep-alive' concerns)
static ref int GetInteriorPointer()
{
ref int pi = ref host_inst.m_i; // managed pointer to interior value-type
host_inst = null; // abandon the heap object itself
return ref pi; // but return the interior pointer
}
static _()
{
ref int pi = ref GetInteriorPointer();
// At this point, the 'outer' container instance itself is not reachable, since
// its only reference was nulled-out. Normally, when an object's last GC handle
// goes out of scope it is eligible for garbage collection.
// However, in this case we still have access to a managed pointer to a field
// inside the object.
// Is 'pi' sufficient to prevent the collection of host_inst here? <-- Question
pi++; // (possible keep-alive... for an inaccessible GC object?)
}
};
问题非常简单:
如果您有一个指向引用类型实例的内部
ValueType
字段的托管指针,但外部实例本身没有句柄,那么是否存在足以使主机保持活动状态的托管指针?
人们可能会怀疑&#34;没有&#34;是的,从IL
来看,托管指针显然是IntPtr
大小,即32位或64位值,就像对象引用一样 - 但在这种情况下没有好处任何&#34;对象标题&#34;或其他明显的元数据支持。 2. 从这看起来,它们似乎太原始或者被剥离了#34;有效地参与GC可达性图。因此,如果托管ref
代表最后剩余的访问方式(某些内部部分)某个对象,但此类ref
指针未在GC图表中跟踪,则该对象将收集。
所以如果答案是&#34;是的,&#34;这是如何运作的?是否存在CLR必须仅在给定托管指针的情况下恢复包含对象的情况,如果是,那将如何完成并且是否有效?
如果答案是&#34;否&#34;并且主机确实碰巧被收集了,托管指针的命运是什么?它是否会在使用时指向垃圾并破坏CLR,还是以某种方式更优雅地处理故障?
请注意,修复程序很简单但确实会影响整体设计:开发人员只需要确保程序独立地在其他地方保留对外部实例的完整引用,并确保它的使用时间超过了托管指针。
[1。] 无限期意思,至少就最初发布托管指针的代码而言,因为客户端可以随意使用或放弃指针,而不是必须报告。
[2.]缺少元数据,因为操作托管指针的IL
指令需要提供TypeRef
作为&#34;烧入&#34;到指令流。
相关:Recover containing GC object from managed 'ref' interior pointer
子>