Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple generated MSIL throws "Operation could destabilize the runtime"

I've created a very simple function that does the following:

    public static object[] ToArray(int ID) {
        return new object[4];
    }

This is the code that generates the MSIL. Why does this throw the "Operation could destabilize the runtime" exception? I can't spot anything wrong with it; it matches the assembly seen in Reflector/Reflexil perfectly.

    // create method
    Type arrayType = typeof(object[]);
    Type intType = typeof(int);
    DynamicMethod dm = new DynamicMethod(methodName, arrayType, new Type[] { intType });
    ILGenerator il = dm.GetILGenerator();

    // create the array -- object[]
    il.Emit(OpCodes.Ldc_I4, 4);
    il.Emit(OpCodes.Newarr, typeof(object));
    il.Emit(OpCodes.Stloc_0);

    // return the array
    il.Emit(OpCodes.Ldloc_0); 
    il.Emit(OpCodes.Ret);

    return dm;
    object result = dm.Invoke(null, new object[] { 1 });
like image 354
Robin Rodricks Avatar asked Oct 05 '22 22:10

Robin Rodricks


1 Answers

I found that the new variable was not declared properly.

You need to use the DeclareLocal(typeof(T)) syntax to declare a new local var.

The updated code snippet is as follows:

    // create method
    Type arrayType = typeof(object[]);
    Type intType = typeof(int);
    DynamicMethod dm = new DynamicMethod(methodName, arrayType, new Type[] { intType });
    ILGenerator il = dm.GetILGenerator();

    // create the array -- object[]
    LocalBuilder arr = il.DeclareLocal(arrayType);
    il.Emit(OpCodes.Ldc_I4, 4);
    il.Emit(OpCodes.Newarr, typeof(object));
    il.Emit(OpCodes.Stloc, arr);  // <-- don't use direct addresses, use refs to LocalBuilder instead

    // return the array
    il.Emit(OpCodes.Ldloc, arr); // <-- don't use direct addresses, use refs to LocalBuilder instead
    il.Emit(OpCodes.Ret);

    return dm;
    object result = dm.Invoke(null, new object[] { 1 });

Edit: Thanks to Jon Skeet, the final optimized code snippet is as follows:

    // create method
    Type arrayType = typeof(object[]);
    Type intType = typeof(int);
    DynamicMethod dm = new DynamicMethod(methodName, arrayType, new Type[] { intType });
    ILGenerator il = dm.GetILGenerator();

    // create the array -- object[]
    LocalBuilder arr = il.DeclareLocal(arrayType);
    il.Emit(OpCodes.Ldc_I4, 4);
    il.Emit(OpCodes.Newarr, typeof(object));

    // return the array
    il.Emit(OpCodes.Ret);

    return dm;
    object result = dm.Invoke(null, new object[] { 1 });
like image 188
Robin Rodricks Avatar answered Oct 10 '22 04:10

Robin Rodricks