Почему PEVerify говорит, что CLR ожидает одномерный массив для массивов статического размера?

Этот код не проходит проверку:

.assembly extern mscorlib {}
.assembly Program {}

.method private static void Main() cil managed
{
    .entrypoint
    .maxstack 3

    .locals init ( int32[0 ... 10] a )

    ldc.i4 10
    newarr int32
    stloc.0

    ldloc.0
    ldc.i4.0
    ldc.i4.s 32
    stelem.i4

    call string [mscorlib]System.Console::ReadLine()
    pop
    ret
}

Со следующей ошибкой:

[IL]: Ошибка: [C: [...] Program.exe: :: Main] [смещение 0x0000000F] Ожидаемый одномерный массив. 1 Ошибка (и) при проверке Program.exe

Тем не менее, этот код отлично проверяет:

.assembly extern mscorlib {}
.assembly Program {}

.method private static void Main() cil managed
{
    .entrypoint
    .maxstack 3

    .locals init ( int32[] a )

    ldc.i4 10
    newarr int32
    stloc.0

    ldloc.0
    ldc.i4.0
    ldc.i4.s 32
    stelem.i4

    call string [mscorlib]System.Console::ReadLine()
    pop
    ret
}

Это нереализованная функция, ошибка в CLR или PEVerify или просто неправильное понимание использования? Обе программы работают нормально.


person Michael J. Gray    schedule 22.12.2011    source источник


Ответы (1)


Я предполагаю - и это только предположение - что это связано с различием между векторами и массивами.

Спецификация интерфейса командной строки ECMA (Раздел II, разделы 14.1 и 14.2) говорит это:

Векторы - это одномерные массивы с нулевой нижней границей. Они имеют прямую поддержку в инструкциях CIL (newarr, ldelem, stelem и ldelema).

[...]

Хотя векторы имеют прямую поддержку с помощью инструкций CIL, все другие массивы поддерживаются VES путем создания подтипов абстрактного класса System.Array.

Векторы объявляются с использованием синтаксиса T[], тогда как массивы могут быть объявлены различными способами с использованием T[n], T[p,q], T[x...y] и т. Д. Итак, в вашем первом примере синтаксис int32[0 ... 10] является объявлением массива. Во втором примере синтаксис int32[] - это объявление vector.

Я предполагаю, что верификатор возражает против вашего первого примера, потому что он думает, что вы пытаетесь использовать newarr и stelem в массиве, а не в векторе. Предположительно, проверяющий проверяет только тип объявления и не принимает во внимание ранг, границы и т. Д. Массива. Причина, по которой оба примера выполняются правильно, заключается в том, что одномерный массив с нулевой нижней границей является вектором для всех намерений и целей.

Что касается того, почему в сообщении об ошибке написано «Ожидаемый одномерный массив», а не «Ожидаемый вектор», я понятия не имею!

person LukeH    schedule 23.12.2011
comment
Значит ли это, что правильный способ индексирования array, как в моем первом примере, - это доступ через его индексатор? - person Michael J. Gray; 23.12.2011
comment
@ Майкл: Я так полагаю. Другой вариант - использовать GetValue, < методы href = "http://msdn.microsoft.com/en-us/library/system.array.setvalue.aspx" rel = "nofollow noreferrer"> _ 2_ и т. д. И вы бы построили его, используя newobj, а не newarr. (В спецификации CLI также говорится, что среда выполнения предоставляет специализированные конструкторы и методы Get и Set, которых нет в метаданных типа Array.) - person LukeH; 23.12.2011