System.AccessViolationException存储带有reflection.emit的变量

时间:2010-07-05 15:56:35

标签: reflection.emit hlsl opcode opcodes

我正在业余时间使用reflection.emit构建一个编译器,我遇到了一个我不理解的问题。

一个小上下文,我有一个运行时有几种类型,其中一个是Float2,一个带有两个浮点值(X和Y)的简单向量结构。我已经制作了一些允许我调整价值的属性(la lalsl)。例如,如果我有一个新的Float2(1.0f,2.0f),如果我做了类似的东西(新的Float2(1.0f,2.0f))。YX我将得到一个Float2(2.0f,1.0f) 我在我的语言中使用这种类型,目前正在测试这种情况(省略了语言的细节):

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 
}

peverify的结果:

[IL]:错误:[偏移量0x0000000F] [找到值'Bifrost.Psl.Compiler.Runtime.Float2'] [预期地址值'Bifrost.Psl.Compiler.Runtime.Float2']堆栈上的意外类型。

1 个答案:

答案 0 :(得分:4)

IL看起来不错,虽然我不知道你的Float2是什么样的。

我发现调试它的最佳方法是将程序集保存到磁盘,然后运行 peverify 。生成AccessViolationException的任何代码都会导致 peverify 出错。

编辑: newobj doc on MSDN讨论了如何将对象引用推送到堆栈,我将其作为指向值类型的指针。如果您从 peverify 收到此错误,那么我认为您需要

  1. newobj
  2. stloc到临时变量
  3. ldloca获取存储在临时变量
  4. 中的值类型的地址
  5. call
  6. 现在我考虑一下,如果你对像4.ToString();这样的值类型进行直接调用,这就是C#编译器的作用。