NET Architecture & Design: Yet another Major JIT Optimizer BUG

  • anonymous / 205 / Fri, 27 Mar 2009 22:01:00 GMT / Comments (21)
  • Try this in Release mode of .Net 1.1 SP1:

    class Bug2
    {
    class C : IDisposable
    {
    public C() {}
    void IDisposable.Dispose() {}
    }

    bool A()
    {
    return true;
    }

    public Bug2()
    {
    if (A())
    {
    Console.WriteLine("A Is True!");
    using (new C()) {}
    }
    else
    {
    Console.WriteLine("A Is False!");
    }
    }
    }
  • Keywords:

    major, jit, optimizer, bug, net, architecture, design

  • http://dotnet.itags.org/dotnet-architecture-design/113564/«« Last Thread - Next Thread »»
    1. Um, I have .Net 1.1 SP1... what's the error you get?

      copied your code into a console project and added the following main():
      [STAThread]
      static void Main(string[] args) {
      Bug2 bg = new Bug2();
      Console.ReadLine();
      }

      the output was:
      A Is True!
      C.Dispose();

      (I changed "void IDisposable.Dispose() {}" to
      "void IDisposable.Dispose() { Console.WriteLine("C.Dispose();"); }"
      )

      Otherwise it remained unchanged... what's the problem?
      Scott

      "Boaz Sedan" <BoazSedan...discussions.microsoft.com> wrote in message
      news:8A797FE8-6380-43C3-9D63-6ECE4A37C53B...microsoft.com...
      > Try this in Release mode of .Net 1.1 SP1:
      > class Bug2
      > {
      > class C : IDisposable
      > {
      > public C() {}
      > void IDisposable.Dispose() {}
      > }
      > bool A()
      > {
      > return true;
      > }
      > public Bug2()
      > {
      > if (A())
      > {
      > Console.WriteLine("A Is True!");
      > using (new C()) {}
      > }
      > else
      > {
      > Console.WriteLine("A Is False!");
      > }
      > }
      > }
      >

      scott | Tues, 20 May 2008 08:40:00 GMT |

    2. If i try it in release build (/o+),
      i get
      A Is True!
      A Is False!

      "Scott Coonce" wrote:

      > Um, I have .Net 1.1 SP1... what's the error you get?
      > copied your code into a console project and added the following main():
      > [STAThread]
      > static void Main(string[] args) {
      > Bug2 bg = new Bug2();
      > Console.ReadLine();
      > }
      > the output was:
      > A Is True!
      > C.Dispose();
      > (I changed "void IDisposable.Dispose() {}" to
      > "void IDisposable.Dispose() { Console.WriteLine("C.Dispose();"); }"
      > )
      > Otherwise it remained unchanged... what's the problem?
      > Scott
      >
      > "Boaz Sedan" <BoazSedan...discussions.microsoft.com> wrote in message
      > news:8A797FE8-6380-43C3-9D63-6ECE4A37C53B...microsoft.com...
      > > Try this in Release mode of .Net 1.1 SP1:
      > >
      > > class Bug2
      > > {
      > > class C : IDisposable
      > > {
      > > public C() {}
      > > void IDisposable.Dispose() {}
      > > }
      > >
      > > bool A()
      > > {
      > > return true;
      > > }
      > >
      > > public Bug2()
      > > {
      > > if (A())
      > > {
      > > Console.WriteLine("A Is True!");
      > > using (new C()) {}
      > > }
      > > else
      > > {
      > > Console.WriteLine("A Is False!");
      > > }
      > > }
      > > }
      > >
      >
      >

      boazsedan | Tues, 20 May 2008 08:41:00 GMT |

    3. Hi Boaz,

      "Boaz Sedan" wrote:
      > If i try it in release build (/o+),
      > i get
      > A Is True!
      > A Is False!
      [...]

      Scary. You seem to have a knack for finding JIT bugs ...

      Kind regards,
      --
      Tom Tempelaere.

      hbb | Tues, 20 May 2008 08:42:00 GMT |

    4. Whoops! Sorry, I overlooked the "Console.WriteLine("A Is False")" in the
      else clause. Once I add this, I too get the A Is True/A Is False combo in
      Release mode, but _not_ Debug.

      I've attached my code file to make sure we test using the exact same code,
      and so anyone else can reproduce the problem.

      Try this: right click the project in the solution explorer -> properties.
      Choose "Configuration-->Release" in combo box
      Select "Configuration Properties-->Build"
      set "Optimize Code" to false

      ... and the problem disappears. I don't know why, though.

      Scott

      "Boaz Sedan" <BoazSedan...discussions.microsoft.com> wrote in message
      news:0F1EF601-332C-44CA-9917-2DFAA0AA1213...microsoft.com...
      > If i try it in release build (/o+),
      > i get
      > A Is True!
      > A Is False!
      > "Scott Coonce" wrote:
      >> Um, I have .Net 1.1 SP1... what's the error you get?
      >> copied your code into a console project and added the following main():
      >> [STAThread]
      >> static void Main(string[] args) {
      >> Bug2 bg = new Bug2();
      >> Console.ReadLine();
      >> }
      >> the output was:
      >> A Is True!
      >> C.Dispose();
      >> (I changed "void IDisposable.Dispose() {}" to
      >> "void IDisposable.Dispose() { Console.WriteLine("C.Dispose();"); }"
      >> )
      >> Otherwise it remained unchanged... what's the problem?
      >> Scott
      >>
      >> "Boaz Sedan" <BoazSedan...discussions.microsoft.com> wrote in message
      >> news:8A797FE8-6380-43C3-9D63-6ECE4A37C53B...microsoft.com...
      >> > Try this in Release mode of .Net 1.1 SP1:
      >> >
      >> > class Bug2
      >> > {
      >> > class C : IDisposable
      >> > {
      >> > public C() {}
      >> > void IDisposable.Dispose() {}
      >> > }
      >> >
      >> > bool A()
      >> > {
      >> > return true;
      >> > }
      >> >
      >> > public Bug2()
      >> > {
      >> > if (A())
      >> > {
      >> > Console.WriteLine("A Is True!");
      >> > using (new C()) {}
      >> > }
      >> > else
      >> > {
      >> > Console.WriteLine("A Is False!");
      >> > }
      >> > }
      >> > }
      >> >
      >>

      begin 666 EntryPoint.cs
      M=7-I;F<...4WES=&5M.PT*=7-I;F<...4WES=&5M+D1I86=N;W-T:6-S.PT*#0IN
      M86UE<W!A8V4...0V]N<V]L951E<W0-"GL-"B ...(&-L87-S($5N=')Y4&]I;G0...
      M>PT*(" ...(" ...6U-4051H<F5A9%T-"B ...(" ...('-T871I8R!V;VED($UA:6XH
      M<W1R:6YG6UT...87)G<RD...>PT*(" ...(" ...(" ...0G5G,B!B9R ](&YE=R!"=6<R
      M*"D[#0H...(" ...(" ...("!#;VYS;VQE+E)E861,:6YE*"D[#0H...(" ...("!]#0H...
      M("!]#0H...("!C;&%S<R!"=6<R('L-"B ...(" ...(&-L87-S($,....B!)1&ES<&]S
      M86)L92![#0H...(" ...(" ...("!P=6)L:6,...0R...I('M]#0H...(" ...(" ...("!V;VED
      M($E$:7-P;W-A8FQE+D1I<W!O<V4H*2![0V]N<V]L92Y7<FET94QI;F4H(D,N
      M1&ES<&]S92...I.R(I.WT-"B ...(" ...('T-"...T*(" ...(" ...8F]O;"!!*"D...>PT*
      M(" ...(" ...(" ...<F5T=7)N('1R=64[#0H...(" ...("!]#0H-"B ...(" ...('!U8FQI
      M8R!"=6<R*"D...>PT*(" ...(" ...(" ...:68...*$$H*2D...>PT*(" ...(" ...(" ...(" ...
      M0V]N<V]L92Y7<FET94QI;F4H(D$...27,...5')U92$B*3L-"B ...(" ...(" ...(" ...
      M('5S:6YG("AN97<...0R...I*2![?0T*(" ...(" ...(" ...?2 -"B ...(" ...(" ...(&5L
      M<V4...>PT*(" ...(" ...(" ...(" ...0V]N<V]L92Y7<FET94QI;F4H(D$...27,...1F%L
      F<V4A(BD[#0H...(" ...(" ...("!]#0H...(" ...("!]#0H...("!]#0I]#0H`
      `
      end

      scott | Tues, 20 May 2008 08:43:00 GMT |

    5. I'm not sure if this helps, but I've decided (for the first time) to dive
      into the IL created for this. It seems that the probem is in the IL and not
      the JIT (which i'd never understand anyway).

      In trying to understand the IL code, I had to go to the msdn library to
      figure it all out, so i copied a bit of the docs to make it easier. Note
      near the bottom that a "goto" (whatever) is missing to jump over the
      Console.WriteLine("A Is False!");

      (I'm a veritable newbie at the IL thing, so I apologize if I'm stating the
      obvious)

      Scott

      Here's the IL for Bug2.ctor():

      .method public hidebysig specialname rtspecialname
      instance void .ctor() cil managed
      {
      //
      // The following is a Release build with
      // Optimization = True.
      //
      // IL documentation comments taken from:
      //
      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemreflectionemitopcodesclassbrfalse_stopic.asp
      //
      //
      // Code size 50 (0x32)
      .maxstack 1
      .locals init (class ConsoleTest.Bug2/C V_0)
      IL_0000: ldarg.0

      // Calls the method indicated by the
      // passed method descriptor, return
      // value pushed onto stack
      IL_0001: call instance void [mscorlib]System.Object::.ctor()

      // Loads the argument at index 0 onto the evaluation stack.
      IL_0006: ldarg.0

      // A() pushes "true" onto stack
      IL_0007: call instance bool ConsoleTest.Bug2::A()

      // Transfers control to a target
      // instruction if value is false,
      // a null reference, or zero.
      IL_000c: brfalse.s IL_0027

      IL_000e: ldstr "A Is True!"
      IL_0013: call void [mscorlib]System.Console::WriteLine(string)

      // pushing an object reference (type O) onto the evaluation stack.
      IL_0018: newobj instance void ConsoleTest.Bug2/C::.ctor()

      // Pops the current value from top of stack
      // and stores it in a the local variable
      // list at index 0.
      // (object "C" stored at 0.)
      IL_001d: stloc.0

      // Loads the local variable at index 0
      // onto the evaluation stack
      // (this is object "C")
      IL_001e: ldloc.0

      // Transfers control to a target
      // instruction if value is false,
      // a null reference, or zero.
      // (since value is "C", it should be non-null, ie. true.)
      IL_001f: brfalse.s IL_0027

      // Loads the local variable at index 0
      // onto the evaluation stack
      // (this is object "C")
      IL_0021: ldloc.0

      // Calls a late-bound method on an
      // object, pushing the return value
      // onto the evaluation stack.
      IL_0022: callvirt instance void [mscorlib]System.IDisposable::Dispose()

      //
      //---
      // It seems that we're missing the "jump" over the
      // "A Is False!" WriteLine
      //---
      //
      IL_0027: ldstr "A Is False!"
      IL_002c: call void [mscorlib]System.Console::WriteLine(string)
      IL_0031: ret
      } // end of method Bug2::.ctor

      scott | Tues, 20 May 2008 08:44:00 GMT |

    6. Two seconds after sending my previous post, I looked at the IL for an exe
      with optimization set to _false_ on a release build.

      Near the end of the method, is this little gem:

      IL_002a: br.s IL_0036
      IL_002c: ldstr "A Is False!"
      IL_0031: call void [mscorlib]System.Console::WriteLine(string)
      IL_0036: ret
      } // end of method Bug2::.ctor

      From the msdn docs, br.s means
      "Unconditionally transfers control to a target instruction (short form)."

      ... just what was missing from the Release w/optimization build.

      Scott

      scott | Tues, 20 May 2008 08:45:00 GMT |

    7. When viewing the debug build and release build in Lutz Reflector here
      is the the what the functions look like for Bug2 constructor.

      Debug build
      public Bug2()
      {
      if (this.A())
      {
      Console.WriteLine("A Is True!");
      using (Bug2.C c1 = new Bug2.C())
      {
      }
      }
      else
      {
      Console.WriteLine("A Is False!");
      }
      }
      Release Build
      public Bug2()
      {
      if (this.A())
      {
      Console.WriteLine("A Is True!");
      Bug2.C c1 = new Bug2.C();
      if (c1 != null)
      {
      ((IDisposable) c1).Dispose();
      }
      }
      Console.WriteLine("A Is False!");
      }

      It looks like it's a bug in the C# compiler and not the IL.

      bravescharm | Tues, 20 May 2008 08:46:00 GMT |

    8. "BravesCharm" <mastrauckas...gmail.com> wrote in message
      > It looks like it's a bug in the C# compiler and not the IL.
      >

      Doesn't the c# compiler do c# code --> IL?
      This is the first step, right?

      Scott

      scott | Tues, 20 May 2008 08:47:00 GMT |

    9. Nothing to do with the JIT / CLR. It's a C# compiler issue.

      "Boaz Sedan" <BoazSedan...discussions.microsoft.com> wrote in message
      news:8A797FE8-6380-43C3-9D63-6ECE4A37C53B...microsoft.com...
      > Try this in Release mode of .Net 1.1 SP1:
      > class Bug2
      > {
      > class C : IDisposable
      > {
      > public C() {}
      > void IDisposable.Dispose() {}
      > }
      > bool A()
      > {
      > return true;
      > }
      > public Bug2()
      > {
      > if (A())
      > {
      > Console.WriteLine("A Is True!");
      > using (new C()) {}
      > }
      > else
      > {
      > Console.WriteLine("A Is False!");
      > }
      > }
      > }
      >

      stuart | Tues, 20 May 2008 08:48:00 GMT |

    10. >Doesn't the c# compiler do c# code --> IL?
      >This is the first step, right?

      The C# compiler produces the IL code that the CLR runs. The IL code
      that the C# compiler created is not correct in release build for some
      reasons.

      bravescharm | Tues, 20 May 2008 08:49:00 GMT |

    11. > ... just what was missing from the Release w/optimization build.

      the compiler incorrecly emits a try-catch block for an empty block (for
      using (...)) with optimizations turned on.
      to see that try to add a code to the "using" block, for example:

      public Bug2() {
      if (A()) {
      Console.WriteLine("A Is True!");
      using (new C())
      {
      Console.WriteLine();
      }
      }
      else {
      Console.WriteLine("A Is False!");
      }
      }

      ...and it will run ok.

      since I was sure this had been noticed long ago, I've spent two minuts and
      here you are, reported over 3 years ago:
      http://tinyurl.com/csjhd

      I wonder if it still exists in the 2.0 version.

      regards,
      Wiktor Zychla

      wiktor | Tues, 20 May 2008 08:50:00 GMT |

    12. >I wonder if it still exists in the 2.0 version.

      No it's been fixed.

      But if it's the same issue as reported three years ago it makes you
      wonder why they haven't fixed it in a SP for v1.x.

      Mattias
      --
      Mattias Sjögren [MVP] mattias ... mvps.org
      http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
      Please reply only to the newsgroup.

      mattias | Tues, 20 May 2008 08:51:00 GMT |

    13. "Mattias Sjögren" <mattias.dont.want.spam...mvps.org> wrote in message
      news:%23Iv7H276FHA.2036...TK2MSFTNGP14.phx.gbl...
      > >I wonder if it still exists in the 2.0 version.
      > No it's been fixed.
      > But if it's the same issue as reported three years ago it makes you
      > wonder why they haven't fixed it in a SP for v1.x.
      >
      > Mattias
      > --
      > Mattias Sjögren [MVP] mattias ... mvps.org
      > http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
      > Please reply only to the newsgroup.

      Yes, it's still the same issue reported before and after v1.1 SP1 was
      released, guess it wasn't too high on the JIT team's priority list.

      Willy.

      willy | Tues, 20 May 2008 08:52:00 GMT |

    14. It's nothing to to with the JIT (or the JIT team). It would be the C#
      compiler team. As others have posted, looking at the IL shows it is
      incorrectly generated when the /o+ flag is used, which comes from the C#
      compiler. If you compiled the example code using the mono or Borland C#
      compiler and ran the same program using the *Microsoft CLR* it would not
      fail.

      Cheers,

      Stu

      "Willy Denoyette [MVP]" <willy.denoyette...telenet.be> wrote in message
      news:%232ibb%2376FHA.2616...TK2MSFTNGP15.phx.gbl...
      > "Mattias Sjögren" <mattias.dont.want.spam...mvps.org> wrote in message
      > news:%23Iv7H276FHA.2036...TK2MSFTNGP14.phx.gbl...
      >> >I wonder if it still exists in the 2.0 version.
      >> No it's been fixed.
      >> But if it's the same issue as reported three years ago it makes you
      >> wonder why they haven't fixed it in a SP for v1.x.
      >>
      >> Mattias
      >> --
      >> Mattias Sjögren [MVP] mattias ... mvps.org
      >> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
      >> Please reply only to the newsgroup.
      > Yes, it's still the same issue reported before and after v1.1 SP1 was
      > released, guess it wasn't too high on the JIT team's priority list.
      > Willy.
      >

      stuart | Tues, 20 May 2008 08:53:00 GMT |

    15. WARNING: Major sarcasm ahead!!!

      MAJOR IT Optimizer BUG? Certainly a bug, not major.

      First, let's add a line inside of the using statement:

      using (new C())
      {
      string x = String.Empty;
      }

      Sure, my x=String.Empty statement is BS, but you did not give much to run
      on. When I add the statement, however, life works again.

      The point here is it is against proper programming practice to chain work to
      your construtor. If you look at OO 101, you end up with the following
      (albeit oversimplified)

      1. Constructors set state
      2. Properties hold state (or internal variables, if you want to get
      technical on the private implementations)
      3. Methods are used for behavior

      As you are using the "using" statement, you should be USING the object, not
      merely filling state. If this is true, the statement:

      using (new C()) {}

      is either a) garbage or b) bad programming practice, which gets us back to
      garbage.

      What is happening in your example is the optimizer is noticing nothing is
      happening with the using statement (i.e., the object is NOT being used). If
      one were to opt to the followign practice (chaining work to the
      constructor), your bug could bite them:

      class C : IDisposable
      {
      public C()
      {
      DoWorkHere();
      }
      void IDisposable.Dispose() {}

      private void DoWorkHere()
      {
      string x = "using the constructor to do work";
      }
      }

      But, the likelihood of actually encountering this bug in a well designed app
      is effectively 0%.

      Bug? Yes.
      Major? Hardly.
      --
      Gregory A. Beamer
      MVP; MCP: +I, SE, SD, DBA

      ***********************************************
      Think Outside the Box!
      ***********************************************
      "Boaz Sedan" <BoazSedan...discussions.microsoft.com> wrote in message
      news:8A797FE8-6380-43C3-9D63-6ECE4A37C53B...microsoft.com...
      > Try this in Release mode of .Net 1.1 SP1:
      > class Bug2
      > {
      > class C : IDisposable
      > {
      > public C() {}
      > void IDisposable.Dispose() {}
      > }
      > bool A()
      > {
      > return true;
      > }
      > public Bug2()
      > {
      > if (A())
      > {
      > Console.WriteLine("A Is True!");
      > using (new C()) {}
      > }
      > else
      > {
      > Console.WriteLine("A Is False!");
      > }
      > }
      > }
      >

      cowboy | Tues, 20 May 2008 08:54:00 GMT |

    16. The compiler puts a try/finally block not a try/catch and when using
      the "using" keyword it will use the try/finally block so it will make
      sure it IDisposable interface gets called even if an exception is
      thrown.

      However, it's only putting this try/finally block in debug mode and not
      release mode. It seems like when it forgets the try/finally it also
      forgets the else too!

      bravescharm | Tues, 20 May 2008 08:55:00 GMT |

    17. Agreed, sorry. Too heavily focused on the subject line I guess.

      Willy.

      "Stuart Carnie" <stuart.carnie...nospam.nospam> wrote in message
      news:OcY5Cg96FHA.476...TK2MSFTNGP15.phx.gbl...
      > It's nothing to to with the JIT (or the JIT team). It would be the C#
      > compiler team. As others have posted, looking at the IL shows it is
      > incorrectly generated when the /o+ flag is used, which comes from the C#
      > compiler. If you compiled the example code using the mono or Borland C#
      > compiler and ran the same program using the *Microsoft CLR* it would not
      > fail.
      > Cheers,
      > Stu
      > "Willy Denoyette [MVP]" <willy.denoyette...telenet.be> wrote in message
      > news:%232ibb%2376FHA.2616...TK2MSFTNGP15.phx.gbl...
      >> "Mattias Sjögren" <mattias.dont.want.spam...mvps.org> wrote in message
      >> news:%23Iv7H276FHA.2036...TK2MSFTNGP14.phx.gbl...
      >> >I wonder if it still exists in the 2.0 version.
      >> No it's been fixed.
      >> But if it's the same issue as reported three years ago it makes you
      >> wonder why they haven't fixed it in a SP for v1.x.
      >>
      >> Mattias
      >> --
      >> Mattias Sjögren [MVP] mattias ... mvps.org
      >> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
      >> Please reply only to the newsgroup.
      >> Yes, it's still the same issue reported before and after v1.1 SP1 was
      >> released, guess it wasn't too high on the JIT team's priority list.
      >> Willy.
      >>
      >

      willy | Tues, 20 May 2008 08:56:00 GMT |

    18. Uzytkownik "BravesCharm" <mastrauckas...gmail.com> napisal w wiadomosci
      news:1132322238.305808.170100...g43g2000cwa.googlegroups.com...
      > The compiler puts a try/finally block not a try/catch and when using
      > the "using" keyword it will use the try/finally block so it will make

      try-finally, of course. a typo.

      Wiktor

      wiktor | Tues, 20 May 2008 08:57:00 GMT |

    19. Absolutely agree.

      "Cowboy (Gregory A. Beamer)" <NoSpamMgbworld...comcast.netNoSpamM> wrote in
      message news:ufbOFbE7FHA.2264...TK2MSFTNGP11.phx.gbl...
      > WARNING: Major sarcasm ahead!!!
      > MAJOR IT Optimizer BUG? Certainly a bug, not major.
      > First, let's add a line inside of the using statement:
      > using (new C())
      > {
      > string x = String.Empty;
      > }
      > Sure, my x=String.Empty statement is BS, but you did not give much to run
      > on. When I add the statement, however, life works again.
      > The point here is it is against proper programming practice to chain work
      > to your construtor. If you look at OO 101, you end up with the following
      > (albeit oversimplified)
      > 1. Constructors set state
      > 2. Properties hold state (or internal variables, if you want to get
      > technical on the private implementations)
      > 3. Methods are used for behavior
      > As you are using the "using" statement, you should be USING the object,
      > not merely filling state. If this is true, the statement:
      > using (new C()) {}
      > is either a) garbage or b) bad programming practice, which gets us back to
      > garbage.
      > What is happening in your example is the optimizer is noticing nothing is
      > happening with the using statement (i.e., the object is NOT being used).
      > If one were to opt to the followign practice (chaining work to the
      > constructor), your bug could bite them:
      > class C : IDisposable
      > {
      > public C()
      > {
      > DoWorkHere();
      > }
      > void IDisposable.Dispose() {}
      > private void DoWorkHere()
      > {
      > string x = "using the constructor to do work";
      > }
      > }
      > But, the likelihood of actually encountering this bug in a well designed
      > app is effectively 0%.
      > Bug? Yes.
      > Major? Hardly.
      > --
      > Gregory A. Beamer
      > MVP; MCP: +I, SE, SD, DBA
      > ***********************************************
      > Think Outside the Box!
      > ***********************************************
      > "Boaz Sedan" <BoazSedan...discussions.microsoft.com> wrote in message
      > news:8A797FE8-6380-43C3-9D63-6ECE4A37C53B...microsoft.com...
      >> Try this in Release mode of .Net 1.1 SP1:
      >> class Bug2
      >> {
      >> class C : IDisposable
      >> {
      >> public C() {}
      >> void IDisposable.Dispose() {}
      >> }
      >> bool A()
      >> {
      >> return true;
      >> }
      >> public Bug2()
      >> {
      >> if (A())
      >> {
      >> Console.WriteLine("A Is True!");
      >> using (new C()) {}
      >> }
      >> else
      >> {
      >> Console.WriteLine("A Is False!");
      >> }
      >> }
      >> }
      >

      stuart | Tues, 20 May 2008 08:58:00 GMT |

    20. Not sure, but the bug is not major, as it requires you use an object without
      actually using it to reproduce it. As soon as you place even one statement
      in the using block, it magically goes away.

      The only way to trigger the bug in an application is to chain behavior to a
      constructor, which is an unwise practice.

      Sure, it is a bug, but it would be low on my priority list, as well.
      --
      Gregory A. Beamer
      MVP; MCP: +I, SE, SD, DBA

      ***********************************************
      Think Outside the Box!
      ***********************************************
      "Mattias Sjögren" <mattias.dont.want.spam...mvps.org> wrote in message
      news:%23Iv7H276FHA.2036...TK2MSFTNGP14.phx.gbl...
      > >I wonder if it still exists in the 2.0 version.
      > No it's been fixed.
      > But if it's the same issue as reported three years ago it makes you
      > wonder why they haven't fixed it in a SP for v1.x.
      >
      > Mattias
      > --
      > Mattias Sjögren [MVP] mattias ... mvps.org
      > http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
      > Please reply only to the newsgroup.

      cowboy | Tues, 20 May 2008 08:59:00 GMT |

    21. NOTE: I am not stating this is not a bug, but trying to illustrate why it
      might have been in there and why it is not MAJOR.

      1. Exceptions are driven by behavior, not state. At least in a properly
      designed system.

      2. As constructors set state and do not trigger behavior, at least in a
      properly designed system, you should not trigger an exception, so the
      compiler apparently "optimizes" out the try ... catch, as there is nothing
      to try.

      Example of a domain object (seat of pants, no design):

      public class User

      {

      public User()

      {

      }

      public User(int userID)

      {

      }

      private int _userId;

      //Other internal variables here

      public property UserId

      {

      get

      {

      return _userId;

      }

      set

      {

      _userId = value;

      }

      }

      //Other properties here

      public void Fill()

      {

      //work done to get user inforamtion

      }

      public void Fill(int userId)

      {

      UserId = userId;

      //chained method to avoid duplicate work

      Fill();

      }

      }

      Calling this with MAJOR bug:

      try

      {

      using(User u = new User(1)){}
      }

      catch
      {
      }

      1. What is there to catch?
      2. When are you going to USE the object?

      If you actually provide something to catch by triggering behavior on the
      constructor, you are creating an object that moves on start (imagine if your
      car did this to see why it is not advised).

      If, instead, you USE the object, the BUG disappears.

      This means you either decide to USE the object (no bug) or have an
      improperly set up object (bad code). If you prefer writing bad code, I can
      see how this is a MAJOR BUG.

      Should the bug be fixed? Yes, an apparently has in 2.0.
      Should code be fixed that actually encounters this particular bug? Yes, as
      it is badly designed.
      --
      Gregory A. Beamer
      MVP; MCP: +I, SE, SD, DBA

      ***********************************************
      Think Outside the Box!
      ***********************************************
      "BravesCharm" <mastrauckas...gmail.com> wrote in message
      news:1132322238.305808.170100...g43g2000cwa.googlegroups.com...
      > The compiler puts a try/finally block not a try/catch and when using
      > the "using" keyword it will use the try/finally block so it will make
      > sure it IDisposable interface gets called even if an exception is
      > thrown.
      > However, it's only putting this try/finally block in debug mode and not
      > release mode. It seems like when it forgets the try/finally it also
      > forgets the else too!
      >

      cowboy | Tues, 20 May 2008 09:00:00 GMT |