从托管的“ ref”内部指针恢复包含GC对象

时间:2018-10-15 21:09:23

标签: .net garbage-collection managed ref

鉴于最新版本的 C#7 中的 ref locals ref return 新功能,该问题是新相关的:

随着C#中托管(或“内部”)指针变量的重要性日益提高和广泛使用,有时您可能需要为此恢复相应的 Pinnable GC对象一个指针。例如,如果要传递指向类型为T的数组元素的托管指针,则可能需要数组引用T[]本身才能调用(例如)Array.Copy(...)

  

因此,根据以下流行的内部/托管指针(ref,{{1中的任何一个),从托管代码中是否有任何合理合法的方法来恢复包含的GC对象句柄。 }},out)使用:

     
      
  1. 指向GC对象实例中的(instruct字段的内部指针;
  2.   
  3. 指向数组class的(structclass元素 T的托管指针。
  4.   


在内部 .NET 中,GC似乎使用了以下功能:/coreclr/master/src/gc/gc.cpp

T[]

此代码遍历已知的GC堆,检查指定的内部指针是否在已知的GC对象分配的范围内。显然,这种方法不易从最终用户管理的代码中访问,而且据我所知,如果没有进行中的GC,甚至可能不适用。

我还浏览了新的#ifdef INTERIOR_POINTERS // will find all heap objects (large and small) uint8_t* gc_heap::find_object (uint8_t* interior, uint8_t* low) { .... Span<T>库,但是找不到一系列的操作来恢复数组句柄(如果您没有从中提供数组句柄的话)第一名(因此,包含这些不同结构的句柄被松散了)。在System.Memory是可选的情况下(例如_pinnable),如果您不选择加入,似乎没有代码可以将其取回。

摘要:有什么方法可以从托管指针中恢复包含对象的句柄吗?

[edit:]如果托管指针指向堆栈上的值类型,则(假定)句柄恢复功能通过(例如)返回“ null”来指示失败将是完全合理的。


相关:How does the C# garbage collector find objects whose only reference is an interior pointer?

1 个答案:

答案 0 :(得分:8)

否,无法从内部指针恢复包含对象。在GC期间,由于所谓的 brick表插入树,内部指针被转换为相应的对象。给定指定的地址,将计算适当的砖块表条目,并遍历相应的插件树以找到该地址所在的插件。最后,逐个对象地扫描该插件,以找到包含所考虑地址的插件。

重点是那些树是仅在GC期间构建并可用的。因此,即使存在这样的“内部指针恢复” API,它也必须等待GC并且只能在之后提供答案(这似乎非常不切实际)。其他解决方案,例如线性内存扫描,显然可能会带来巨大的开销。