System.AccessViolationException, сохраняющий переменную с reflectio.emit - PullRequest
1 голос
/ 05 июля 2010

В свободное время я создаю компилятор с mirror.emit, и у меня возникла проблема, которую я не понимаю.

Небольшой контекст, у меня есть среда выполнения спара типов, и один из них - Float2, более простая векторная структура с двумя значениями с плавающей точкой (X и Y).Я сделал несколько свойств, которые позволяют мне менять значения (a la hlsl).Например, если у меня есть новый Float2 (1.0f, 2.0f), если я сделаю что-то вроде (новый Float2 (1.0f, 2.0f)). YX я собираюсь получить Float2 (2.0f, 1.0f) IЯ использую этот тип в моем языке и в настоящее время тестирую этот случай (незначительные детали языка пропущены):

float2 a = float2(1.0, 2.0).yx;
return a;

Я преобразую float2 (1.0, 2.0) в новый вызов и получаю доступ к свойству YXмоего типа Float2 в .yx.

Проблема в том, что я получаю «System.AccessViolationException: Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена.».Я не понимаю почему, потому что если я сделаю что-то вроде этого:

float2 a = float2(1.0, 2.0);
return a;

Все идет хорошо.

Код IL, который я генерирую, следующий (я думаю, что проблема возникает в «L_0014: stloc.0», хотя я не знаю, почему это происходит):

    .method public virtual final instance valuetype
[Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 Main() cil managed
{
    .maxstack 3
    .locals init (
        [0] valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 num)
    L_0000: ldc.r4 1
    L_0005: ldc.r4 2
    L_000a: newobj instance void [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::.ctor(float32, float32)
    L_000f: call instance valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::get_XY()
    L_0014: stloc.0 
    L_0015: ldloc.0 
    L_0016: ret 
}

Результат проверки:

[IL]: ошибка: [смещение 0x0000000F] [найденное значение 'Bifrost.Psl.Compiler.Runtime.Float2'] [ожидаемый адрес значения 'Bifrost.Psl.Compiler.Runtime.Float2 '] Неожиданный тип в стеке.

1 Ответ

4 голосов
/ 05 июля 2010

ИЛ выглядит нормально, хотя я не знаю, как выглядит ваш Float2.

Я нашел лучший способ отладки: сохранить сборку на диск, а затем запустить peverify . Любой код, который генерирует AccessViolationException, вызовет ошибку в peverify .

Редактировать: Документ newobj на MSDN говорит о переносе ссылки на объект в стек, который я считал указателем на тип значения. Если вы получаете эту ошибку от peverify , тогда я думаю, что вам нужно

  1. newobj
  2. stloc к временной переменной
  3. ldloca для получения адреса типа значения, хранящегося во временной переменной
  4. call

Теперь, когда я думаю об этом, это то, что делает компилятор C #, если вы делаете прямой вызов для типа значения, такого как 4.ToString();.

...