c# - 像 C# 方法 IL 一样发出 IL 但获取 System.InvalidProgramException : Common Language Runtime detected an invalid program

标签 c# clr emit

像 C# 方法 IL 一样发出 IL 但获取 System.InvalidProgramException:公共(public)语言运行时检测到无效程序。

示例:

    public static int BoolToInt(this bool input)
    {
        return input ? 1 : 0;
    }

IL 代码是:

ExtensionDataGetter.BoolToInt:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  brtrue.s    IL_0007
IL_0004:  ldc.i4.0    
IL_0005:  br.s        IL_0008
IL_0007:  ldc.i4.1    
IL_0008:  stloc.0     
IL_0009:  br.s        IL_000B
IL_000B:  ldloc.0     
IL_000C:  ret         

我尝试使用 Emit IL 来创建这个方法:

class Program
{
    static void Main(string[] args)
    {
        var result = CreateFunc()(true);
        Console.WriteLine(result);
    }

    static Func<bool, int> CreateFunc()
    {
        var dm = new DynamicMethod("Test" + Guid.NewGuid().ToString(), typeof(int), new[] { typeof(bool) });
        var il = dm.GetILGenerator();

        il.Emit(OpCodes.Nop);
        il.Emit(OpCodes.Ldarg_0);

        var labelTrue = il.DefineLabel();
        var labelStloc = il.DefineLabel();
        var labelReturn = il.DefineLabel();

        il.Emit(OpCodes.Brtrue_S, labelTrue); 
        il.Emit(OpCodes.Ldc_I4_0);
        il.Emit(OpCodes.Br_S, labelStloc);
        il.MarkLabel(labelTrue);
        il.Emit(OpCodes.Ldc_I4_1);
        il.MarkLabel(labelStloc);
        il.Emit(OpCodes.Stloc_0);

        il.Emit(OpCodes.Br_S, labelReturn); 
        il.MarkLabel(labelReturn);
        il.Emit(OpCodes.Ldloc_0); 
        il.Emit(OpCodes.Ret);

        var funcType = System.Linq.Expressions.Expression.GetFuncType(typeof(bool), typeof(int));
        return (Func<bool, int>)dm.CreateDelegate(funcType);
    }
}

但是得到以下错误

System.InvalidProgramException
  HResult=0x8013153A
  Message=Common Language Runtime detected an invalid program.
  Source=<Cannot evaluate the exception source>
  StackTrace:
<Cannot evaluate the exception stack trace>

我试着按照我的逻辑写一个新版本,它成功了。
但它是 IL 不等于演示方法的 IL

using System;
using System.Reflection;
using System.Reflection.Emit;


class Program
{
    static void Main(string[] args)
    {
        var func = CreateFunc();
        Console.WriteLine(func(true));
        Console.WriteLine(func(false));
    }

    static Func<bool, int> CreateFunc()
    {
        var dm = new DynamicMethod("Test" + Guid.NewGuid().ToString(), typeof(int), new[] { typeof(bool) });

        var il = dm.GetILGenerator();
        var labelTrue = il.DefineLabel();

        il.Emit(OpCodes.Nop);
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Brtrue_S, labelTrue); 
        il.Emit(OpCodes.Ldc_I4_0);
        il.Emit(OpCodes.Ret);
        il.MarkLabel(labelTrue);
        il.Emit(OpCodes.Ldc_I4_1);
        il.Emit(OpCodes.Ret);

        var funcType = System.Linq.Expressions.Expression.GetFuncType(typeof(bool), typeof(int));
        return (Func<bool, int>)dm.CreateDelegate(funcType);
    }
}


最佳答案

由于您使用 STLoc.0 将值存储在局部变量中,因此您需要声明它:

var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int));

你的第二个版本没有使用本地化,所以它没有这个问题。

第一个版本是编译器在 Debug模式下发出的,但在 Release模式下它更像是你的第二个例子(除了 nop 是不必要的)。

关于c# - 像 C# 方法 IL 一样发出 IL 但获取 System.InvalidProgramException : Common Language Runtime detected an invalid program,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58129941/

相关文章:

c# - 删除数据表中的主键

.net - 为什么 CLR 对象类型是可序列化的?

c# - 在 C# 中使用 foreach 循环时的内存分配

c# - VB.NET 中的 foreach 是否比 c# 中的更快?

angular - TypeError : instance[output. propName].subscribe 不是函数

c++ - 如何使用 yaml-cpp 发出不带引号的字符串?

c# - BitConverter.ToInt32 是如何工作的?

c# - System.Windows.ResourceReferenceKeyNotFoundException

c# - 使用 Entity Framework 将更改保存回数据库

c - GCC 不会发出我的指令,我试图避免分支