System.AccessViolationException 使用 Reflectio.emit 存储变量

发布于 2024-09-07 21:56:24 字数 1432 浏览 6 评论 0原文

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

一点上下文,我有一个具有几种类型的运行时,其中之一是 Float2,这是一个具有两个浮点值(X 和 Y)的更简单的向量结构。我创建了几个属性,允许我调整值(la hlsl)。例如,如果我有一个新的 Float2(1.0f, 2.0f),如果我做了类似 (new 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]:错误:[offset 0x0000000F ] [发现值“Bifrost.Psl.Compiler.Runtime.Float2”][值“Bifrost.Psl.Compiler.Runtime.Float2”的预期地址]堆栈上的意外类型。

I'm building a compiler with reflection.emit in my spare time, and i've come to a problem that i'm not understanding.

A little context, I've a runtime with a couple of types and one of them is Float2, a simpler vector struct with two float values (X and Y). I've made a couple of properties that allow me to swizzle the values (a la hlsl). For example if i have a new Float2(1.0f, 2.0f), if i make something like (new Float2(1.0f, 2.0f)).YX i'm going to get a Float2(2.0f, 1.0f)
I'm using this type in my language and currently testing this case (minor details of the language omitted):

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

I'm transforming float2(1.0, 2.0) in a new call and accessing the property YX of my Float2 type in .yx.

The problem is I'm getting a "System.AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.". I don't understand why because if I make something like this:

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

Everything goes well.

The IL code that i'm generating is the following (I think the problem occurs in "L_0014: stloc.0", I don't know why it happens though) :

    .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 
}

Result of peverify:

[IL]: Error: [offset 0x0000000F]
[found value 'Bifrost.Psl.Compiler.Runtime.Float2'][expected address of value 'Bifrost.Psl.Compiler.Runtime.Float2'] Unexpected type on the stack.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

〃温暖了心ぐ 2024-09-14 21:56:24

IL 看起来不错,尽管我不知道您的 Float2 是什么样的。

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

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

  1. newobj
  2. stloc 到临时变量
  3. ldloca获取存储在临时变量
  4. call

中的值类型的地址现在我想了一下,如果您直接调用像 4 这样的值类型,这就是 C# 编译器所做的事情.ToString();

The IL looks OK, although I don't know what your Float2 looks like.

I found the best way to debug this is to save the assembly to disk, then run peverify. Any code that generates an AccessViolationException will cause an error in peverify.

Edit: The newobj doc on MSDN talks about pushing an object reference onto the stack, which I took to be a pointer to a value type. If you're getting this error from peverify then I think you need to

  1. newobj
  2. stloc to a temporary variable
  3. ldloca to get the address of the value type stored in the temporary variable
  4. call

Now that I think about it, this is what the C# compiler does if you do a direct call on a value type like 4.ToString();.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文