2015-06-05 3 views
4

Согласно ECMA-335:Адрес, где элемент сразу за концом массива будет храниться

II.14.4.2 управляемых указателей

Управляемые указатели (&) может указывать на экземпляр типа значения, поле объекта, поле значения типа, элемент массива или адрес , где элемент, расположенный за концом массива, будет содержать (для указателей указателей в управляемые массивы).

Последняя часть меня интересует. Означает ли это, что ссылка за пределами массива действительна? Как получается такая ссылка (возможно, с ИЛ)? Как CLR обрабатывает чтение и письмо?

+1

Да, ссылка действительна. Разделение указателя - нет. В противном случае очень распространенное поведение, также используемое в C++, например, возвращает функцию end() класса коллекции. GC может справиться с этим, ссылка на объект не указывает на начало объекта, поэтому указатель end() нельзя путать с другим объектом. –

+0

@HansPassant Разве разыменование делает исключение или что-то еще? – IllidanS4

+0

Вызов разыменования указателей не проверяется, шансы на AccessViolationException довольно низки. Не равен нулю. Вы просто получаете мусор. –

ответ

3

Это означает, что указатель действителен, но это не значит, что разыменование является действительным.

Например, если у вас есть массив, содержащий 10 значений Int32, что означает 10 * 4 байта, указатель на 40-й байт после начала массива действителен.

Выявление разницы это не так.

Это означает, что чтение или запись недействительны.

+0

Интересно, как GC может сказать, что этот указатель относится к массиву, а не к объекту, который сразу же следует за массивом в памяти. – usr

+0

Это не так. Указатели не сохраняют объекты живыми, ссылаются на них. –

+0

Но управляемые указатели необходимо отрегулировать, когда объекты перемещаются. Это не закрепленные внутренние указатели, верно? – usr

2

Подумайте о сегментированной «защищенной» памяти.

Заявление, которое вы цитируете, вторит стандарту C++, в котором подробно описывается, как указатель-прошлый конец должен быть действительным и безопасным для сравнения. Большая часть библиотеки C++ (алгоритмы) использует этот тип указателей как «дозорный», эквивалентный, например, EOF.

С защищенной памятью просто загрузка значения указателя вне пространства процесса в регистр может привести к ошибке защиты. Он не будет ждать разыменования.

Здесь фактически сказано, что последний байт ваших данных может не быть последним байтом выделенного сегмента. Диспетчер памяти должен будет добавить 1 или более байт. Таким образом, позволяя компилятору/оптимизатору всегда использовать адресный регистр для указателей.