从托管'ref'内部指针恢复包含 GC 对象



鉴于最新版本的 C# 7中的新 reflocalsref 返回功能,这个问题是新的相关问题:

随着 C# 中托管或"内部"指针变量的日益突出和广泛使用,有时您可能需要为此类指针恢复相应的包含PinnableGC 对象。例如,如果要将托管指针传递到类型为T的数组元素,则可能需要数组引用本身T[]才能调用(例如(Array.Copy(...)

那么,从托管代码中,是否有任何合理合法的方法来恢复包含的 GC 对象句柄,给定以行的内部/托管指针(refoutin(使用:

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

.NET内部,GC 似乎使用以下函数:/coreclr/master/src/gc/gc.cpp

#ifdef INTERIOR_POINTERS
// will find all heap objects (large and small)
uint8_t* gc_heap::find_object (uint8_t* interior, uint8_t* low)
{
....

此代码演练已知的 GC 堆,检查指定的内部指针是否在已知 GC 对象分配的范围内。显然,这种方法不容易从最终用户托管的代码中访问,据我所知,如果没有正在进行的 GC,甚至可能无关紧要。

我还查看了新的Span<T>System.Memory库,但找不到一系列操作来恢复(例如(数组句柄,如果你不首先提供它(其中包含句柄在这些不同的结构中被蠕动(。在_pinnable是可选的(例如Span<T>(,结构中的 GC 句柄是null的,因此如果您从一开始就不选择加入,则无法将其取回。

摘要:有没有办法从托管指针恢复包含对象句柄?

[编辑:] 如果托管指针指向堆栈上的值类型,则(假定的(句柄恢复函数通过(例如(返回"null"来指示失败是完全合理的。


相关:C# 垃圾回收器如何查找其唯一引用是内部指针的对象?

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

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

相关内容

  • 没有找到相关文章

最新更新