【问题标题】:Possible bug in JIT or CLRJIT 或 CLR 中可能存在的错误
【发布时间】:2015-01-24 18:27:53
【问题描述】:

我的代码生成一个方法来动态创建一个假设维度长度数组的多维数组,但是 JIT 编译器甚至 CLR 似乎都无法从维度长度数组中适当地加载项目。

不是创建int[10, 10, 10] 的数组,而是创建int[10, 10, 0] 的数组。在OpCodes.Ldelem_I 似乎出错了,但是,使用OpCodes.Ldelem, typeof(int) 就可以了。重现此行为,需要任何 CPU 设置,x86 工作正常。调试和发布模式都会出现此问题。

所以这是一个错误吗?我无法判断这一点,因为我无法更深入地研究这一点。

class Program
{
    static void Main(string[] args)
    {
        CreateMultidimensionalArrayCreator(typeof(int[, ,])).Invoke(new int[] { 10, 10, 10 }); ;            
    }

    static Func<int[], Array> CreateMultidimensionalArrayCreator(Type type)
    {
        int rank = type.GetArrayRank();

        DynamicMethod method = new DynamicMethod(String.Empty, typeof(Array), new Type[] { typeof(int[]) }, typeof(Program), false);
        ILGenerator ilGen = method.GetILGenerator();

        for (int i = 0; i < rank; i++)
        {
            // Load element from dimension lengths array
            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldc_I4, i);
            ilGen.Emit(OpCodes.Ldelem_I); // Somehow returns 0 for last element, however, OpCodes.Ldelem appears to work fine
            // Duplicate element and write to console for diagnostics
            ilGen.Emit(OpCodes.Dup);
            ilGen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }));
        }

        // Get parameters for multidimensional array constructor
        //
        Type[] parameterTypes = new Type[rank];

        for (int i = 0; i < rank; i++)
        {
            parameterTypes[i] = typeof(int);
        }

        ilGen.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null));
        ilGen.Emit(OpCodes.Ret);

        return (Func<int[], Array>)method.CreateDelegate(typeof(Func<int[], Array>));
    }
}

【问题讨论】:

  • 这个程序输出了一些数字,你能告诉我们你观察到什么和你期望什么,而不是像你的文字暗示的那样吗?
  • @LasseV.Karlsen - Here 是有形的屏幕截图。
  • 我在 VS2015 上也得到了 10,10,10
  • 你知道'native int`是一个指针吗?你应该使用Ldelem_I4 代替Int32
  • 不,这并不奇怪,64 位上的native int 基本上是Int64。顺便说一句,使用Ldelem_I4 时一切正常。我建议您将 IL 转储到程序集并在其上运行 PEVerify。它在类型问题上出错。

标签: c# .net clr jit reflection.emit


【解决方案1】:

换行:

ilGen.Emit(OpCodes.Ldelem_I); // Somehow returns...

到行:

ilGen.Emit(OpCodes.Ldelem_I4); // Somehow returns 0 for last element....

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2019-04-18
    • 2013-10-11
    相关资源
    最近更新 更多