Этот вопрос актуален в свете новых ref locals и ref return функций в последних версиях C # 7 :
Из-за возросшей известности и более широкого использования переменных управляемых или «внутренних» указателей в C # иногда может понадобиться восстановить соответствующий содержащий Pinnable
объект GC для такого указателя.Например, если вы передаете управляемый указатель на элемент массива типа T
, вам может понадобиться ссылка на массив T[]
, чтобы вызвать (например) Array.Copy(...)
.
* 1017.* Таким образом, из управляемого кода существует ли
разумно допустимый способ восстановления дескриптора содержащего объект GC, с использованием одного из следующих преобладающих внутренних / управляемых указателей (
ref
,
out
,
in
)использует:
- Внутренний указатель на (
struct
или class
) поле в экземпляре объекта GC; - Управляемый указатель на (
struct
или class
) элемент T
массива 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>
), кажется, что если вы не согласитесь, нет кода, который сможет вернуть его.
Сводка: Есть ли способ восстановить дескриптор содержащего объекта из управляемого указателя?
[edit:] Если управляемый указатель указывает на тип значения в стеке, это было бы совершенно разумно для (предполагаемого) обрабатывать функцию восстановления, чтобы указать на ошибку, (например, возвращая 'null'.
Related: Как сборщик мусора в C # находит объекты, единственной ссылкой на которые является внутренний указатель?