5

Possible Duplicate:
SEHException .net Conundrum

A Colleague pointed out this interesting exception which has started getting generated recently. (note this is a toy version of the actual code, for simplicity)

using System;

namespace ConsoleApplication19
{
    class Program
    {
         static void Main(string[] args)
        {
            var o1 = new MyObject?(new MyObject(2.34M));
            o1 *= -1; //This line throws SEHException
         }
    }

    public struct MyObject
    {
        public MyObject(Decimal myValue)
        {
            this.myValue = myValue;
        }

        private Decimal myValue;

        public static MyObject operator *(MyObject value1, Decimal value2)
        {
            value1.myValue *= value2;
            return value1;
        }
   }
}

The marked line throws an SEHException 'External component threw an exception'. Obviously the error is that -1 on that line should be -1M, so the arg is of the correct type, this change stops the exception being thrown. What's interesting though is by making a minor 'cosmetic' change to the code the exception is no longer thrown.

// If you invert the order of the operands to MyObject.*() , and expand out the *= in main,
// the thing runs without throwing the exception :s

// If you step through, the value of myValue is correctly ‘invalid decimal value’ after * by -1.

using System;

namespace ConsoleApplication19
{
    class Program
    {
        static void Main(string[] args)
        {
            var o1 = (MyObject?)new MyObject(2.34M);
            o1 = -1 * o1 ;
        }
    }

    public struct MyObject
    {
        private Decimal myValue;

        public MyObject(Decimal myValue)
        {
            this.myValue = myValue;
        }

        public static MyObject operator *(Decimal value2,  MyObject value1)
        {
            value1.myValue *= value2;
            return value1;
    }
    }
}

Note all we've done is inverted the order of the arguments to the * defined for MyObject, and expanded the *= to be more explicit. I was thinking maybe the fact that the values get pushed to the stack in a different order avoids the exception? But I'm pretty clueless.

Just to clarify: I don't need a solution to stop the exception being thrown, we have that, I'm more interested in why the exception is being thrown, and why making minor cosmetic changes to the code 'fixes' the issue.

hint: also been advised that the exception isn't thrown in visual studio 2010, only 2008.

Any help is appreciated :)

Community
  • 1
  • 1
teenan
  • 159
  • 3
  • What environment are you using? I've tried this on x86 in Visual Studio 2010 (Release + Debug) and am not seeing th error. – JaredPar Mar 29 '11 at 16:38
  • Please mention C#/CLR version. –  Mar 29 '11 at 16:58
  • sorry, not at work at the moment so can't check exactly, only details I know off the top of my head are running visualStudio 2008, with .net 4. I can get more details later in work. As I mentioned in the post, the error doesn't occur in VS2010. – teenan Mar 29 '11 at 17:29
  • well spotted Hans, I missed that one before I posted. Looks like one of the guys at work beat me too it. – teenan Mar 29 '11 at 17:49
  • @hans are you able to close this as a duplicate? – jwwishart Apr 01 '11 at 03:43
  • @jww - I can't, flagged a moderator. – Hans Passant Apr 01 '11 at 03:46

0 Answers0