Восстановить содержащий объект GC из управляемого внутреннего указателя ref - PullRequest
0 голосов
/ 16 октября 2018

Этот вопрос актуален в свете новых ref locals и ref return функций в последних версиях C # 7 :

Из-за возросшей известности и более широкого использования переменных управляемых или «внутренних» указателей в C # иногда может понадобиться восстановить соответствующий содержащий Pinnable объект GC для такого указателя.Например, если вы передаете управляемый указатель на элемент массива типа T, вам может понадобиться ссылка на массив T[], чтобы вызвать (например) Array.Copy(...).

* 1017.* Таким образом, из управляемого кода существует ли разумно допустимый способ восстановления дескриптора содержащего объект GC, с использованием одного из следующих преобладающих внутренних / управляемых указателей (ref, out, in)использует:
  1. Внутренний указатель на (struct или class) поле в экземпляре объекта GC;
  2. Управляемый указатель на (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 # находит объекты, единственной ссылкой на которые является внутренний указатель?

1 Ответ

0 голосов
/ 16 октября 2018

Нет, восстановление содержащего объекта из внутреннего указателя невозможно.Во время GC внутренние указатели преобразуются в соответствующие объекты благодаря так называемым кирпичным таблицам и вставным деревьям .При заданном адресе вычисляется соответствующая запись таблицы кирпичей, и соответствующее дерево плагинов просматривается, чтобы найти плагин, в котором этот адрес живет.Наконец, этот плагин сканируется объект за объектом, чтобы найти тот, который содержит рассматриваемый адрес.

Дело в том, что эти деревья построены и доступны только во время GC.Таким образом, даже если бы существовал такой API «восстановления внутреннего указателя», ему пришлось бы ждать GC и дать ответ только после этого (что представляется очень непрактичным).Другие решения, такие как линейное сканирование памяти, очевидно, могут привести к огромным накладным расходам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...