Компилятор Just-In-Time в .NET выполняет две важные функции при преобразовании MSIL, сгенерированного компилятором C#, в исполняемый машинный код. Очевидным и видимым является генерирование машинного кода. Неочевидное и полностью невидимое задание создает таблицу, которая сообщает сборщику мусора, где искать ссылки на объекты, когда GC происходит во время выполнения метода.
Это необходимо, потому что корни объектов нельзя просто сохранить в куче GC, как поле класса, но также хранится в локальных переменных или регистры процессора. Чтобы правильно выполнить эту работу, джиттер должен знать точную структуру фрейма стека и типы хранимых там переменных, чтобы он мог правильно создать эту таблицу. Таким образом, позже сборщик мусора может выяснить, как прочитать правильное смещение фрейма стека или регистр CPU, чтобы получить значение корня объекта. Указатель на кучу GC.
Это проблема, когда вы используете stackalloc
. Этот синтаксис использует функцию CLR, которая позволяет программе объявлять пользовательский тип значения. Задняя дверь вокруг обычных объявлений с управляемым типом с ограничением на то, что этот тип значения не может содержать никаких полей. Просто капля памяти, это зависит от программы для создания правильных смещений в этом блобе. Компилятор C# помогает вам создавать эти смещения на основе объявления типа и выражения индекса.
Также очень распространенная в программе C++/CLI та же функция пользовательского типа значений может предоставить хранилище для собственного объекта C++. Требуется только пространство для хранения этого объекта, правильная его инициализация и доступ к членам этого объекта C++ - это задание, которое компилятор C++ определяет. Ничто из того, что GC не должен знать.
Таким образом, основное ограничение заключается в том, что нет способа предоставить информацию о типе для этой ячейки памяти. Что касается CLR, это просто простые байты без структуры, таблица, которую использует GC, не имеет возможности описать ее внутреннюю структуру.
Неизбежно, единственный тип типа, который вы можете использовать, - это тип, который не требует ссылки на объект, о которой должен знать GC. Блестящие типы значений или указатели. Так что System.String - это не-go, это ссылочный тип. Ближе вы могли бы получить, что это «тягучий» является:
char** mem = stackalloc char*[100];
С дальнейшим ограничением, что это полностью зависит от вас, чтобы убедиться, что символ * элементы указывают либо возлагали или неуправляемого строки. И что вы не индексируете «массив» вне пределов. Это не очень практично.
У вас есть указатель на управляемый тип на C#, он просто не встроен в язык, как в C++/CLI. https://msdn.microsoft.com/en-us/library/1246yz8f(v=vs.110).aspx - Использовать GCHandleType.Pinned как второй аргумент, а затем вызвать AddrOpPinnedObject() в результате. – Nuzzolilo
@Nuzzolilo Вы пробовали? Если я правильно помню, вы получите исключение, если попытаетесь «GCHandleType.Pinned» управляемый объект. – xanatos
Я помню, что сделал это много лет назад, но это было так долго, что моя память могла быть неправильной: P. Я попробую еще раз и посмотрю, что произойдет. – Nuzzolilo