代码之家  ›  专栏  ›  技术社区  ›  Glenn Slayden

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

  •  3
  • Glenn Slayden  · 技术社区  · 7 年前

    参考局部变量 和 ref返回 C#7级 :

    随着C#中托管指针变量(或“内部”指针变量)的日益突出和广泛使用,有时可能需要恢复相应的 包含 Pinnable 这样一个指针的GC对象。例如,如果要传递指向类型为的数组元素的托管指针 T ,可能需要数组引用 T[] 为了召唤(例如) Array.Copy(...) .

    那么,托管代码中是否有 恢复包含GC对象句柄的方法,给定以下任意一个内部/托管指针( ref , out , in )用途:

    1. 指向( struct class ) 在GC对象实例中;
    2. 指向( 结构 班 要素 T 数组的 T[]


    内部 .NET /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 是可选的(例如。 ),似乎如果你不选择加入,就没有代码能把它取回。

    总结:

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


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

    1 回复  |  直到 7 年前
        1
  •  11
  •   Glenn Slayden    7 年前

    不,无法从内部指针恢复包含对象。在GC期间,由于所谓的 砖制桌子 塞树 . 给定一个指定的地址,计算适当的砖块表条目并遍历相应的插件树,以找到该地址所在的插件。最后,逐个对象扫描该插件,以找到包含所考虑的地址的插件。

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

    推荐文章