CIL и проверка привязки массива - PullRequest
2 голосов
/ 25 января 2012

Допустим, следующая CIL-программа:

.assembly extern mscorlib {}
.assembly Program {}

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

    .locals init ( int32[] a,
               uint32   t )

    // Creates an array of int of size 10
    ldc.i4 10
    newarr int32
    stloc.0

    // Writes 0xaabbccdd at the index 2 of the array
    ldloc.0
    ldc.i4.2
    ldc.i4 0xaabbccdd
    stelem.i4

    // Loads
    ldloc.0
    ldc.i4 9 // <HERE>
    ldelem.i1

    stloc.1
    ldstr "Value: 0x{0:x8}"
    ldloc.1
    box [mscorlib]System.UInt32
    call void [mscorlib]System.Console::WriteLine(string, object)

    ret
}

Эта программа:

  • создает массив типа int 10
  • записывает 0xaabbccdd в индекс 2 массива
  • пытается прочитать один байт в массиве, используя ldelem.i1
  • печатает результат

Хитрость в том, что я использую «ldelem.i1» вместо более стандартного «idelem.i4» для проблем с производительностью (я хочу избежать маскирования). Идея состоит в том, чтобы получить доступ к данным массива так, как это делается с указателями в к.

Но все не так хорошо, потому что программа аварийно завершает работу (IndexOutOfRangeException) для индексов более 10 в качестве аргумента для ldelem.i1. Это делает трюк бесполезным, так как я не могу получить доступ к данным после первой половины целого числа в третьем индексе.

В идеале я хочу получить доступ к байтам до индекса 39, что соответствует последнему байту целого числа в индексе 9.

Я был бы очень признателен, если бы у кого-то были идеи на этот счет.

1 Ответ

3 голосов
/ 25 января 2012

Интересно. ECMA-335 заявляет, что он выдаст исключение, если индекс больше или равен размеру массива, который он определенно равен . Что меня удивляет в этом, так это не то, что генерируется исключение, а то, что индекс обрабатывается как индекс byte в массиве int , во-первых - я не вижу что это указано в любом месте.

Я подозреваю вы находитесь в сферах неопределенного поведения, вполне возможно поведение, которое не предназначено для указания - я подозреваю, вы просто не должны использовать ldelem.i1 в массиве int.

...