1

空き時間にreflection.emitでコンパイラを構築していて、理解できない問題に遭遇しました。

ちょっとしたコンテキストですが、いくつかの型を持つランタイムがあり、そのうちの 1 つは Float2 です。これは、2 つの float 値 (X と Y) を持つ単純なベクター構造体です。値を入れ替えることができるプロパティをいくつか作成しました (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 
}

検証の結果:

[IL]: エラー: [オフセット 0x0000000F] [値 'Bifrost.Psl.Compiler.Runtime.Float2' が見つかりました][値 'Bifrost.Psl.Compiler.Runtime.Float2' の予想されるアドレス] スタックに予期しない型があります。

4

1 に答える 1

4

IL は問題ないように見えますが、あなたがどのように見えるかはわかりませんFloat2

これをデバッグする最善の方法は、アセンブリをディスクに保存してからpeverifyを実行することです。を生成するコードは、 peverifyAccessViolationExceptionでエラーを引き起こします。

編集: newobjMSDNのドキュメントでは、オブジェクト参照をスタックにプッシュすることについて説明しています。これは、値型へのポインターであると見なされました。peverifyからこのエラーが発生している場合は、次のようにする必要があると思います

  1. newobj
  2. stloc一時変数に
  3. ldloca一時変数に格納されている値型のアドレスを取得する
  4. call

考えてみると、これは、 のような値型を直接呼び出す場合に C# コンパイラが行うことです4.ToString();

于 2010-07-05T16:01:54.230 に答える