Откуда берутся маркеры Label_ в Reflector и как их расшифровать?

StackOverflow https://stackoverflow.com/questions/1367712

Вопрос

Я пытаюсь понять метод, используя функцию разборки Reflector.Любой, кто использовал этот инструмент, знает, что определенный код отображается с метками C#, которые (предположительно) не использовались в исходном исходном коде.

В методе 110 строк, который я рассматриваю, есть 11 заявлений этикетки.Примеры случайных фрагментов:

Label_0076:
    if (enumerator.MoveNext())
    {
        goto Label_008F;
    }
    if (!base.IsValid)
    {
        return;
    }
    goto Label_0219;
Label_0087:
    num = 0;
    goto Label_01CB;
Label_01CB:
    if (num < entityArray.Length)
    {
        goto Label_0194;
    }
    goto Label_01AE;
Label_01F3:
    num++;
    goto Label_01CB;

Какой код заставляет Reflector отображать эти метки повсюду и почему он не может их дизассемблировать?

Существует ли хорошая методика их расшифровки?

Это было полезно?

Решение

Вы смотрите на код, сгенерированный компилятором.Компилятор вас не уважает.Нет, правда.Он не уважает ни меня, ни кого-либо еще.Он смотрит на наш код, издевается над нами и переписывает его, чтобы он работал максимально эффективно.

Вложенные операторы if, рекурсия, «yield», операторы case и другие сокращения кода приведут к тому, что код будет выглядеть странно.И если вы используете лямбды с большим количеством вложений, не ждите, что это будет красиво.

В любом месте, при любой возможности компилятор сможет переписать ваш код, чтобы он работал быстрее, так и будет.Таким образом, не существует какого-то «своего рода кода», который мог бы вызвать это.Reflector изо всех сил старается дизассемблировать, но не может отличить исходный код автора от его переписанной версии.Он делает все возможное (что иногда даже неправильно!), чтобы перевести IL в некоторую форму приемлемого кода.

Если вам сложно его расшифровать, вы можете вручную отредактировать код, включив в него встроенные переходы, которые вызываются только один раз, и реорганизовать переходы, вызываемые более одного раза, в вызовы методов.Другой альтернативой является дизассемблирование на другой язык.Код, который переводит IL на языки более высокого уровня, не один и тот же.Декомпилятор C++/CLI может сделать вашу работу лучше и при этом быть достаточно похожим (найти/заменить -> на .), чтобы его можно было понять.

На самом деле для этого не существует панацеи;по крайней мере, пока кто-нибудь не напишет лучший плагин для дизассемблера.

Другие советы

На самом деле компилятор C# не выполняет никакой оптимизации — он оставляет это на усмотрение JIT-компилятора (или ngen).Таким образом, генерируемый им IL довольно последователен и предсказуем, поэтому такие инструменты, как Reflector, могут так эффективно декомпилировать IL.Одна из ситуаций, когда компилятор преобразует ваш код, — это итератор метод.Метод, который вы рассматриваете, вероятно, содержал что-то вроде:

foreach(var x in something)
  if(x.IsValid)
    yield return x;

Поскольку преобразование итератора может быть довольно сложным, Reflector не может с ним справиться.Чтобы понять, что искать, напишите свои собственные методы-итераторы и запустите их через Reflector, чтобы увидеть, какой тип IL генерируется на основе вашего кода C#.Тогда вы будете знать, что искать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top