Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4597312
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 21, 20262026-05-21T23:14:21+00:00 2026-05-21T23:14:21+00:00

Working on a SQLHelper class to automate stored procedures calls in a similar way

  • 0

Working on a SQLHelper class to automate stored procedures calls in a similar way to what is done in the XmlRpc.Net library, I have hit a very strange problem when running a method generated manually from IL code.

I’ve narrowed it down to a simple generated method (probably it could be simplified even more). I create a new assembly and type, containing two methods to comply with

public interface iTestDecimal
{
    void TestOk(ref decimal value);
    void TestWrong(ref decimal value);
}

The test methods are just loading the decimal argument into the stack, boxing it, checking if it’s NULL, and if it is not, unboxing it.

The generation of TestOk() method is as follows:

static void BuildMethodOk(TypeBuilder tb)
{
    /* Create a method builder */
    MethodBuilder mthdBldr = tb.DefineMethod( "TestOk", MethodAttributes.Public | MethodAttributes.Virtual,
      typeof(void), new Type[] {typeof(decimal).MakeByRefType() });

    ParameterBuilder paramBldr = mthdBldr.DefineParameter(1,  ParameterAttributes.In | ParameterAttributes.Out, "value");
    // generate IL
    ILGenerator ilgen = mthdBldr.GetILGenerator();

    /* Load argument to stack, and box the decimal value */
    ilgen.Emit(OpCodes.Ldarg, 1);

    ilgen.Emit(OpCodes.Dup);
    ilgen.Emit(OpCodes.Ldobj, typeof(decimal));
    ilgen.Emit(OpCodes.Box, typeof(decimal));

    /* Some things were done in here, invoking other method, etc */
    /* At the top of the stack we should have a boxed T or null */

    /* Copy reference values out */

    /* Skip unboxing if value in the stack is null */
    Label valIsNotNull = ilgen.DefineLabel();
    ilgen.Emit(OpCodes.Dup);

    /* This block works */
    ilgen.Emit(OpCodes.Brtrue, valIsNotNull);
    ilgen.Emit(OpCodes.Pop);
    ilgen.Emit(OpCodes.Pop);
    ilgen.Emit(OpCodes.Ret);
    /* End block */

    ilgen.MarkLabel(valIsNotNull);
    ilgen.Emit(OpCodes.Unbox_Any, typeof(decimal));

    /* Just clean the stack */
    ilgen.Emit(OpCodes.Pop);
    ilgen.Emit(OpCodes.Pop);
    ilgen.Emit(OpCodes.Ret);
}

The building for TestWrong() is nearly identical:

static void BuildMethodWrong(TypeBuilder tb)
{
    /* Create a method builder */
    MethodBuilder mthdBldr = tb.DefineMethod("TestWrong", MethodAttributes.Public | MethodAttributes.Virtual,
    typeof(void), new Type[] { typeof(decimal).MakeByRefType() });

    ParameterBuilder paramBldr = mthdBldr.DefineParameter(1,  ParameterAttributes.In | ParameterAttributes.Out, "value");

    // generate IL
    ILGenerator ilgen = mthdBldr.GetILGenerator();

    /* Load argument to stack, and box the decimal value */
    ilgen.Emit(OpCodes.Ldarg, 1);
    ilgen.Emit(OpCodes.Dup);
    ilgen.Emit(OpCodes.Ldobj, typeof(decimal));
    ilgen.Emit(OpCodes.Box, typeof(decimal));

    /* Some things were done in here, invoking other method, etc */
    /* At the top of the stack we should have a boxed decimal or null */

    /* Copy reference values out */

    /* Skip unboxing if value in the stack is null */
    Label valIsNull = ilgen.DefineLabel();
    ilgen.Emit(OpCodes.Dup);

    /* This block fails */
    ilgen.Emit(OpCodes.Brfalse, valIsNull);
    /* End block */

    ilgen.Emit(OpCodes.Unbox_Any, typeof(decimal));
    ilgen.MarkLabel(valIsNull);

    /* Just clean the stack */
    ilgen.Emit(OpCodes.Pop);
    ilgen.Emit(OpCodes.Pop);
    ilgen.Emit(OpCodes.Ret);
}

The only difference is I’m using BrFalse instead of BrTrue to check if the value in the stack is null.

Now, running the following code:

iTestDecimal testiface = (iTestDecimal)SimpleCodeGen.Create();

decimal dectest = 1;
testiface.TestOk(ref dectest);
Console.WriteLine(" Dectest: " + dectest.ToString());

The SimpleCodeGen.Create() is creating a new assembly and type, and calling the BuildMethodXX above to generate the code for TestOk and TestWrong.
This works as expected: does nothing, value of dectest is not changed. However, running:

iTestDecimal testiface = (iTestDecimal)SimpleCodeGen.Create();

decimal dectest = 1;
testiface.TestWrong(ref dectest);
Console.WriteLine(" Dectest: " + dectest.ToString());

the value of dectest is corrupted (sometimes it gets a big value, sometimes it says “invalid decimal value”, …) , and the program crashes.

May this be a bug in the JIT, or am I doing something wrong?

Some hints:

  • In debugger, it happens only when “Suppress JIT optimizations” is disabled. If “Suppress JIT optimizations” is enabled, it works. This makes me think the problem must be in the JIT optimized code.
  • Running the same test on Mono 2.4.6 it works as expected, so this is something specific for Microsoft .NET.
  • Problem appears when using datetime or decimal types. Apparently, it works for int, or for reference types (for reference types, the generated code is not identical, but I’m omiting that case as it works).
  • I think this link, reported long time ago, might be related.
  • I’ve tried .NET framework v2.0, v3.0, v3.5 and v4, and behavior is exactly the same.

I’m omitting the rest of the code, creating the assembly and type. If you want the full code, just ask me.

Thanks very much!

Edit: I’m including the rest of the assembly and type creation code, for completion:

class SimpleCodeGen
{
    public static object Create()
    {
        Type proxyType;

        Guid guid = Guid.NewGuid();
        string assemblyName = "TestType" + guid.ToString();
        string moduleName = "TestType" + guid.ToString() + ".dll";
        string typeName = "TestType" + guid.ToString();

        /* Build the new type */
        AssemblyBuilder assBldr = BuildAssembly(typeof(iTestDecimal), assemblyName, moduleName, typeName);
        proxyType = assBldr.GetType(typeName);
        /* Create an instance */
        return Activator.CreateInstance(proxyType);
    }

    static AssemblyBuilder BuildAssembly(Type itf, string assemblyName, string moduleName, string typeName)
    {
        /* Create a new type */
        AssemblyName assName = new AssemblyName();
        assName.Name = assemblyName;
        assName.Version = itf.Assembly.GetName().Version;
        AssemblyBuilder assBldr = AppDomain.CurrentDomain.DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder modBldr = assBldr.DefineDynamicModule(assName.Name, moduleName);
        TypeBuilder typeBldr = modBldr.DefineType(typeName,
          TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public, 
          typeof(object), new Type[] { itf });

        BuildConstructor(typeBldr, typeof(object));
        BuildMethodOk(typeBldr);
        BuildMethodWrong(typeBldr);
        typeBldr.CreateType();
        return assBldr;
    }

    private static void BuildConstructor(TypeBuilder typeBldr, Type baseType)
    {
        ConstructorBuilder ctorBldr = typeBldr.DefineConstructor(
          MethodAttributes.Public | MethodAttributes.SpecialName |
          MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
          CallingConventions.Standard,
          Type.EmptyTypes);

        ILGenerator ilgen = ctorBldr.GetILGenerator();
        //  Call the base constructor.
        ilgen.Emit(OpCodes.Ldarg_0);
        ConstructorInfo ctorInfo = baseType.GetConstructor(System.Type.EmptyTypes);
        ilgen.Emit(OpCodes.Call, ctorInfo);
        ilgen.Emit(OpCodes.Ret);
    }

    static void BuildMethodOk(TypeBuilder tb)
    {
        /* Code included in examples above */
    }

    static void BuildMethodWrong(TypeBuilder tb)
    {
        /* Code included in examples above */           
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-21T23:14:21+00:00Added an answer on May 21, 2026 at 11:14 pm

    Look at this part of your code:

    ilgen.Emit(OpCodes.Dup);
    ilgen.Emit(OpCodes.Brfalse, valIsNull);
    ilgen.Emit(OpCodes.Unbox_Any, typeof(decimal));
    ilgen.MarkLabel(valIsNull);
    

    After the first line, the top of the stack will contain two object references. You then conditionally branch, removing one of the references. The next line unboxes the reference to a decimal value. So where you mark your label, the top of the stack is either an object reference (if the branch was taken) or a decimal value (if it wasn’t). These stack states are not compatible.

    EDIT

    As you point out in your comment, your IL code following this would work if the stack state has a decimal on top or if it has an object reference on top, since it just pops the value off of the stack either way. However, what you’re trying to do still won’t work (by design): there needs to be a single stack state at each instruction. See section 1.8.1.3 (Merging stack states) of the ECMA CLI spec for more details.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Working in Java: I have a JFrame class, and separate classes for my two
Working in Scala-IDE, I have a Java library, in which one of the methods
Working on a simple poker script in PHP and need a way to determine
Working on a project at the moment and we have to implement soft deletion
Working on a website http://www.ArenaText.com written in asp.net with Microsoft AJAX control toolkit. iPad
Working example: http://alpha.jsfiddle.net/gTpWv/ Both of the methods work separately, but once regexp for smilies
Working with a Lucene index, I have a standard document format that looks something
Working on my first Android app and facing a challenge. I am pulling calls
Working on game. I have a movable basket and a - for now -
Working with a base64 encoding for Azure (http://msdn.microsoft.com/en-us/library/dd135726.aspx) and I dont seem to work

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.