Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Microsoft .NET Release Bug

0.00/5 (No votes)
14 Jun 2007 1  
This article demonstrates a Microsoft .NET Release bug. Gives tips to solve a Release Bug.

Screenshot - ReleaseBug.jpg

Introduction

This article demonstrates a major flaw in the Microsoft .NET Framework 1.1. To my knowledge, there isn't a patch to fix the problem.

Background

You may ask ... "What is a Release Bug?"

A release bug is the outcome of code that was written to be output differently when compiled in different modes. Take for example that you have a simple program that adds two variables, and outputs the data. Say the input values were (2, 2) and the result returned SHOULD BE EQUAL to 4. If compiled in debug mode you get the answer 4 and in release mode you get the answer 5. Sounds funny? It's NOT FUNNY AT ALL! This is a real problem. Now the example I just used does not produce a RELEASE BUG, but was just for you to understand the scope of the problem.

Now there are 4 different ways that a program can be run:

  1. Through the Visual Studio IDE in DEBUG mode
  2. Through the Visual Studio IDE in RELEASE mode
  3. Run the EXECUTABLE that was compiled in DEBUG mode
  4. Run the EXECUTABLE that was compiled in RELEASE mode (this is where the RELEASE BUG appears)

Three of the four running applications will return the same results, while that last will return irregular results. Release bugs are some of the hardest bugs to find. Nowhere is there a compile error, logical error, warning, or anything at all. Sorry there is one thing ... NOTHING. When sifting through 60,000+ lines of code to look for this, it becomes quite complex. Don't give up, they are possible to find.

The code compiled here demonstrates the problem I encountered and what I did to fix it. I also explain ways to help fix the problems.

Using the code

The real heart of the bug resides in the FindMSBandLSB_Math Method. This is my original method for finding the MSB (Most Significant Bit) from the mask value. I figured that this would be the fastest method because only one line of code would be called verses 10-20 lines of code. In attempting to speed up processing, I caused the program to produce irregular results (due to a Release Bug). The Release Bug occurs in this line of code:

msbPos = (int) ( Math.Log(++maskVal) / Math.Log(2) ) - 1;

NOTE: When finding the problem, you will need to narrow down the files, and think about what line of code could be causing the problem. Find the possible class and then find the line of code that causes the error. Modify the code to produce the desired output in a completely different way. Test your application. Then test your application in Release mode outside of the IDE. If you can't figure out the line of code and what your code output in release mode is, then don't worry, you can still do it. Read below for the instructions.

Once the bug was found, I modified the code to guarantee that I would not run into the same problem. I did this by applying bit shifting techniques. For more information on bit shifting, view Wikipedia's explanation of Bitwise Operation. In the process of changing code, I decided to test to see how much slower the new code would be. To my surprise, the bit shifting method seemed to give me a processing gain of 33%.

The method to find the MSB looks like this:

// Find the LSB position (RIGHT MOST position set to '1')

while( ( (maskVal & 0x1) == 1 ) && (maskVal) != 1 )
{
    ++msbPos;

    // Shift one to the right and check that value next

    maskVal >>= 1;
}

This is the method to find the MSB and LSB. The Release Bug happens when trying to calculate the MSB. The code looks like this:

private void FindMSBandLSB_Math
            (string mask, out uint msbPos, out uint lsbPos)
{
    lsbPos = 0;
    msbPos = 0;

    // Store the mask value in a byte array

    ulong maskVal = ulong.Parse
        (mask, System.Globalization.NumberStyles.HexNumber, null);

    // Make sure the mask value is not ZERO

    if( maskVal > 0 )
    {
        for(int i = 0; i < nTimes; i++)
        {
            lsbPos = 0;
            msbPos = 0;

            // Find the LSB position (RIGHT MOST position set to '1')

            while( (maskVal & 0x1) == 0u )
            {
                ++lsbPos;

                // Shift one to the right and check that value next

                maskVal >>= 1;
            }

            if( maskVal == 1u )
            {
                // Only one bit is set. MSB must equal LSB.

                msbPos = lsbPos;
            }
            else
            {
                /***********************************************************/
                /*    Find the MSB position (LEFT MOST position set to '1')*/
                /***********************************************************/
                //

                //     n+1            (Using the 'maskVal', find 'n' )

                //    2    = maskVal      and then you have the MSB position)

                //

                //----------------------------------------------------------

                //

                //        ln( maskVal + 1 )

                //    n = ----------------- + ( -1 )

                //              ln( 2 )

                //

                //-----------------------------------------------------------

                //

                //    EXAMPLE: maskVal = 255

                //

                //             15<---------------0

                //    decimal notation = 0000 0000 1111 1111

                //                  ^----- msbPos = 7

                //

                //        ln( 255 + 1 )

                //    n = ------------- + (-1)

                //           ln( 2 )

                //

                // Find the MSB position (LEFT MOST position set to '1')

                msbPos = (uint) ( Math.Log(maskVal + 1) / Math.Log(2) ) - 1;

                // Add the LSB position to it, 

            // and you have the final MSB position

                msbPos += lsbPos;
            }
        }
    }
    else
    {
    throw new ArgumentNullException
    ( "Mask Value" , "The mask value must have at least one bit set." );
    }
}

This is the revised method that fixes the Release Bug (using bitwise operations).

private void FindMSBandLSB_Bits(string mask, out uint msbPos, out uint lsbPos)
{
    lsbPos = 0;
    msbPos = 0;

    // Store the mask value in a byte array

    ulong maskVal = ulong.Parse
        (mask, System.Globalization.NumberStyles.HexNumber, null);

    // Make sure the mask value is not ZERO

    if( maskVal > 0 )
    {
        for(int i = 0; i < nTimes; i++)
        {
            lsbPos = 0;
            msbPos = 0;

            // Find the LSB position (RIGHT MOST position set to '1')

            while( (maskVal & 0x1) == 0 )
            {
                ++lsbPos;

                // Shift one to the right and check that value next

                maskVal >>= 1;
            }

            // Set the MSB bit

            msbPos = lsbPos;

            // Only do if more than one bit is set

            if( maskVal != 1 )
            {
                // Find the LSB position (RIGHT MOST position set to '1')

                while( ( (maskVal & 0x1) == 1 ) && (maskVal) != 1 )
                {
                    ++msbPos;

                    // Shift one to the right and check that value next

                    maskVal >>= 1;
                }
            }
        }
    }
    else
    {
        throw new ArgumentNullException( "Mask Value" , 
            "The mask value must have at least one bit set." );
    }
}

How the Application Works

This application was written to take a HEXADECIMAL value (example: 0FFF) and convert it to BINARY (0000 1111 1111 1111). The BINARY value would then be used to find the Least Significant Bit (LSB) and Most Significant Bit (MSB). When reading the binary value, we will read the bits from right to left starting at position ZERO. The LSB bit will be the first set bit from the right. The MSB bit will be the last bit position set from the right. Bits are turned on by being set to 1. They are turned off by being set to 0. In this example, the LSB bit is 0 and the MSB bit is 11.

Temporary Fix

While attempting to find the problem and fix it, you can apply a temporary workaround by doing the following:

  1. Set the solution build to "Release".
  2. Right click on the project in the "Solution Explorer" that has the bug.
  3. Select "Properties".
  4. Select "Configuration Properties".
  5. Set "Optimize Code" to False.
  6. Set "Generate Debugging Information" to True.

OR

  • Set the solution build to "Debug" does the same thing.

(UPDATED)

If you use the first or second workaround, then make sure to find the Release Bug and set the Project Properties back.

How to Solve a Release Bug

There is no way that I can tell you where your problem resides in your code. To narrow down your issue, figure out what method of code is executing that causes the problem. This may be your hardest step. Next find the lines of code that are complex or non-standard. Make sure to breakout long statements into multiple lines and output messages to display the result of each line. Always remember that you are running your application outside of the IDE, and you will not be able to set breakpoints or run debugging code. Rely on output messages to show you where the line of code goes askew. After you find the line of code that executes a release bug, then rewrite the method or line so that you do not produce the bug again.

(UPDATED)
Post your code online for help if you need to (forums work well for this), and check Microsoft Support website for the problem. Also this should be obvious, but GOOGLE your error and see if someone else has had the problem.

Points of Interest

  • I figured that one line of code (the LOG function) would be faster than iterating through each bit to find what bits are set. I WAS WRONG! When optimizing code, "shorter does not equal faster!"
  • Release bugs are an annoying problem, and very difficult to fix. Half the battle is understanding that Release Bugs problems exist.
  • (UPDATED)
    Microsoft will put out patches for some of these bugs. If a bug exists, then you may need to contact Microsoft for a patch that they do not release to everybody, or they wait for a service pack.
  • Whatever you do, don't give up on finding the bug!

Let me Prove the Bug to You

Values to demonstrate the RELEASE BUG with this application include the following values: (NOTE: '0x' represents that the value is a HEX)

  • 0x7
  • 0x0FC
  • 0x0FFF
  • 0x1C
  • 0x1F8
  • .....find one for yourself!

Please Comment on the BUG

Please post your comments on this bug found in the .NET framework. If you find that it does not work on your computer, then please let me know. I am curious to know if there is a patch or fix that has been released. I know that Microsoft release patches only to problems. This seems to be a big problem to me. Mathematical operations on a floating-point values is not a good thing.

A bug like this can cause disastrous results. READ ABOUT SOFTWARE BUGS on WIKIPEDIA!

The article on WIKIPEDIA reads: "Most bugs arise from mistakes and errors made by people in either a program's source code or its design, and a few are caused by compilers producing incorrect code ..."

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here