问题描述
鉴于最新版本的 C#7 中的 ref locals 和 ref return 新功能,该问题是新相关的:
This question is newly relevant in light of the new ref locals and ref return features in the latest versions of C# 7:
随着C#中托管(或内部)指针变量的重要性日益增强和广泛使用,有时您可能需要恢复各自包含的 Pinnable
此类指针的GC对象。例如,如果您传递的托管指针指向类型为 T
的数组元素,则可能需要数组引用 T []
本身,以便调用(例如) Array.Copy(...)
。
With the increased prominence and wider use of managed--or "interior"--pointer variables in C#, occasionally you may need to recover the respective containing Pinnable
GC object for such a pointer. For example, if you are passing around a managed pointer to an array element of type T
, you might need the array reference T[]
itself in order to call (e.g.) Array.Copy(...)
.
- 指向(
结构
或class
)的内部指针GC对象实例中的> field ; - 指向(
struct
或class的托管指针
)元素T
数组T []
。
- Interior pointer to a (
struct
orclass
) field within a GC object instance; - Managed pointer to a (
struct
orclass
) elementT
of ArrayT[]
.
内部 .NET ,看来GC使用了以下功能:
Internally in .NET, it appears that the GC uses the following function: /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,甚至可能不适用。
This code walks through known GC heaps checking for whether the specified interior pointer falls within the range of the known GC object allocations. Obviously, this method is not readily accessible from end-user managed code and, for all I know, may not even be relevant if there's no GC in progress.
查看了新的 Span< T>
和 System.Memory
库,但找不到一系列的操作序列如果您不是从一开始就提供数组句柄的话,它将恢复(例如)数组句柄(从而包含句柄被那些不同的结构压缩掉了)。在 _pinnable
是可选的情况下(例如 Span< T>
),如果您不选择-in,没有代码可以找回它。
I also looked through the new Span<T>
and System.Memory
libraries, but couldn't find a sequence of manipulations that would recover an (e.g.) array handle if you didn't start by providing it in the first place (whereby the containing handle gets squirreled away in those various structs). In cases where the _pinnable
is optional (e.g. Span<T>
), it seems that if you don't opt-in, there's no code that's able to get it back.
摘要:有什么方法可以从托管对象中恢复包含对象的句柄。
Summary: Is there any way to recover the containing object handle from a managed pointer?
[edit:]如果托管指针指向堆栈上的值类型,则(假定的)句柄恢复函数指示该指针将是完全合理的
[edit:] If the managed pointer points to a value-type on the stack, it would be perfectly reasonable for the (putative) handle recovery function to indicate failure by (e.g.) returning 'null'.
推荐答案
不,从内部指针恢复包含对象是不可能。在GC期间,由于所谓的 brick表和插入树,内部指针被转换为相应的对象。给定指定的地址,将计算适当的砖块表条目,并遍历相应的插件树以找到该地址所在的插件。最后,逐个对象地扫描该插件,以找到包含所考虑地址的插件。
No, recovery of the containing object from an interior pointer is not possible. During GC, interior pointers are translated into corresponding objects thanks to the so-called brick table and plug trees. Given a specified address, the proper brick table entry is calculated and corresponding plug tree is traversed to find the plug within which that address lives. Finally, that plug is scanned object-by-object to find the one that contains the considered address.
要点是,这些树是在GC期间构建并可用的。因此,即使存在这样的内部指针恢复 API,它也必须等待GC并且只能在之后提供答案(这似乎非常不切实际)。其他解决方案,例如线性内存扫描,显然可能会带来巨大的开销。
The point is those trees are built and available only during GC. So, even if such an "interior pointer recovery" API existed, it would have to wait for the GC and could provide an answer only afterwards (which seems very impractical). Other solutions, like linear memory scanning, would obviously possibly introduce tremendous overhead.
这篇关于从托管的“ ref”内部指针恢复包含GC对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!