Is it a BUG in C# compiler ?!!!!

  • Thread starter Thread starter Dmitry Bond.
  • Start date Start date
D

Dmitry Bond.

Hi All.

I faced with strange behavior of C# compiler - in some cases it generates
not working code!
I mean code that lead to the exception - System.InvalidProgramException:
Common Language Runtime detected an invalid program.

The situation is following - 3rd vendor library generates a class that
contains too big InitializeComponent method (copy-paste of
InitializeComponent method to empty text file gives us 23.100 lines and size
= 1.9mb). When calls this method is called application immediately crashed
with the message - "System.InvalidProgramException: Common Language Runtime
detected an invalid program."

Content of InitializeComponent is similar to such methods in Windows.Forms
or Asp.Net application - there are initializations of components properties
ans so on - nothing special, just lot of assignments; no local variables -
ony class members used.

Just by a guess I tried to split up that method to more small pieces of
code - InitializeComponent1, InitializeComponent2 and so on. After that
mentioned error disappeared - all things begin to work fine.
I tested this case on 3 different computers - this error is stable (btw, I
my computer is Pentium4-3GHz/1Gb RAM/120Gb HDD, then I do not think that
error could appears because of weak computer).
One more case I tested - Debug and Release builds of that application -
mentioned error appears constantly only in Debug build, Release build of the
application works fine.

And one more interesting thing - this error stable appears in VS.Net 2003
and VS.Net 2005 Beta2.
Then is could be a problem of new VS.Net too.

My questions are:
Is it a BUG in C# compiler? Is it limitation of compiler? Where such
limitations described?
Should I think my conclusion about reason of this error (I mean - too many
code in one class method) is correct?
Or perhaps you could see any other possible reasons of the problem? Which?
Could we expect Microsoft to release the patch in the nearest future?
Or should we ask 3rd vendor to implement the workaround I found (I mean -
splitting up big method to smaller)?

The problem is very serious for us, please help!


WBR,
Dmitry.
 
My questions are:
Is it a BUG in C# compiler? Is it limitation of compiler? Where such
limitations described?

It is as likely not a bug in the compiler as it is one. However it does look
like a bug. The question is if it is in the compiler(generating bad code at
some point) or if its in the runtime\JIT haivng a problem with some code
sequence. Try running peverify on it to see if it can give you an idea of
whats wrong, and if you know the platform well enough, analyzing the IL,
specifically the differences in the release and debug builds.
Should I think my conclusion about reason of this error (I mean - too many
code in one class method) is correct?

Without testing it myself, I can't say for sure, but the evidence you give
certainly suggests it. You might want to run something like
Could we expect Microsoft to release the patch in the nearest future?

This is an odd bug, they may not know about it. Try reporting it to product
services(don't know how to off hand, but someone else here should.)
Or should we ask 3rd vendor to implement the workaround I found (I mean -
splitting up big method to smaller)?

I'd talk to the 3rd party vendor, they are smaller and will probably be able
to fix the problem far faster than MS. They also might be able to put more
pressure on MS to fix the problem. It is odd they havn't run into this
circumstance.
 
Thank you for answer.

Yes, I know about PEVERIFY. Sorry I forget to say - I run it and it said all
is ok:

All Classes and Methods in TestStiApp2.exe Verified

Then, perhaps it could be a problem of JIT/VM...

to-All: does anybody know how to contact MS product services to report this
problem?
I browsed microsoft.com for a 20 minutes but unfortunately not found how to
submit problem report.
Looks like such task is far non trivial for MS, isn't it?... ;-)
 
Dmitry said:
Then, perhaps it could be a problem of JIT/VM...

I think it is a problem with JIT or the execution engine. To be honest,
a method with over 23 thousand lines is extreme. That is a bug in the
vendor's code IMO. The vendor should delay some of this initialization.

Richard
 
Dmitry,

Well, I was able to reproduce the exception, but I don't think it's a
bug. What I found is that there is a limit to the number of local
variables you can declare in a method. That limit is 32767. Anything
more than that will generate the said exception. I also attempted to
find a limit to the size of the method. I made it up to 2^20 lines of
code in a single method that produced a ~25MB source file and compiled
to ~13MB before I gave up. ILDASM, though slow, was quite content when
I forced it to show me the contents of that method. What was amazing
though was that it only took ~8 seconds to JIT compile the method. Not
too bad eh?

Brian
 
Hi Richard,

Richard Grimes said:
I think it is a problem with JIT or the execution engine. To be honest, a
method with over 23 thousand lines is extreme. That is a bug in the
vendor's code IMO. The vendor should delay some of this initialization.

Richard

If .NET does not have a documentation entry that limits this, then the
vendor's code does not have a bug. Although I think 23000 lines is a lot,
there is by my knowledge no limit to the number of executed statements
inside a function.

Anyway, documentation on InvalidProgramException:
<quote>
The exception that is thrown when a program contains invalid Microsoft
intermediate language (MSIL) or metadata. Generally this indicates a bug in
the compiler that generated the program.
</quote>

Since the compiler was able to compile the generated program without
compilation errors or ICE's, the compiler in question generated bad IL.

Kind regards,
 
Hi Brian,

Brian Gideon said:
Dmitry,

Well, I was able to reproduce the exception, but I don't think it's a
bug. What I found is that there is a limit to the number of local
variables you can declare in a method. That limit is 32767. Anything
more than that will generate the said exception. I also attempted to
find a limit to the size of the method. I made it up to 2^20 lines of
code in a single method that produced a ~25MB source file and compiled
to ~13MB before I gave up. ILDASM, though slow, was quite content when
I forced it to show me the contents of that method. What was amazing
though was that it only took ~8 seconds to JIT compile the method. Not
too bad eh?

Brian

Where does the limitation apply? To the C# language? To the MSIL?

If the C# compiler didn't complain when compiling the code, then isn't the
compiler in fault? It should know the limits of the IL, or shouldn't it?

Kind regards,
 
TT said:
Hi Brian,



Where does the limitation apply? To the C# language? To the MSIL?

If the C# compiler didn't complain when compiling the code, then isn't the
compiler in fault? It should know the limits of the IL, or shouldn't it?

You bring up a good point. If there is a limitation to IL then it
should be in the specification somewhere. If it is in the
specification then the bug lies in the C# compiler. But, if it isn't
then the bug lies in the JIT compiler. Either way there is a bug
somewhere.
 
TT said:
If .NET does not have a documentation entry that limits this, then the
vendor's code does not have a bug. Although I think 23000 lines is a
lot, there is by my knowledge no limit to the number of executed
statements inside a function.

Well, I think that is passing the buck, although I take your point
(albeit a double negative point) that if the spec doesn't say you cannot
do it, then that means that you should be able to do it.

As to a limit, well, of course there is one. The spec says that IL of a
method is preceded by a header, either fat format or tiny format. Tiny
format uses 6 bits to say how many bytes (not opcodes, but the total of
opcodes and their parameters) that make up the method. Clearly tiny
format is not used in this monster method <g>. The fat format uses 4
bytes (ie it's a uint) to give the number of bytes. (Partitian II 24.4.1
to 24.4.3) Of course, it's very doubtful that in this case the number of
bytes has been exceeded.
Anyway, documentation on InvalidProgramException:
<quote>
The exception that is thrown when a program contains invalid Microsoft
intermediate language (MSIL) or metadata. Generally this indicates a
bug in the compiler that generated the program.
</quote>

Since the compiler was able to compile the generated program without
compilation errors or ICE's, the compiler in question generated bad
IL.

True. Someone on the C# team should have put in a count the number of
local variable (as another poster suggested was the problem) and threw
an error. However, having said that, I would not recommend anyone to buy
a tool that produces such monsterous code, regardless of whether it was
'correct' or not.

Richard
 
Richard said:
As to a limit, well, of course there is one. The spec says that IL of a
method is preceded by a header, either fat format or tiny format. Tiny
format uses 6 bits to say how many bytes (not opcodes, but the total of
opcodes and their parameters) that make up the method. Clearly tiny
format is not used in this monster method <g>. The fat format uses 4
bytes (ie it's a uint) to give the number of bytes. (Partitian II 24.4.1
to 24.4.3) Of course, it's very doubtful that in this case the number of
bytes has been exceeded.

Richard,

After reviewing the CLI specification (ECMA 335, ISO/IEC 23271) I have
discovered that it appears the local variable limitation should be
65534 (Partition II Section 22.2.6 LocalVarSig) and not 32767 as I
observed.

"Count is an unsigned integer that holds the number of local variables.
It can be any number between 1 and 0xFFFE."

This leads me to believe that it is a bug with the JIT compiler. I
wish I had saved my tests so that I could quickly generate a method
with more than 65534 local variables to see if the C# compiler would
complain. I may do that when I get time.

Brian
 
Hello.

Richard Grimes said:
TT said:
If .NET does not have a documentation entry that limits this, then the
vendor's code does not have a bug. Although I think 23000 lines is a
[...skip...]

an error. However, having said that, I would not recommend anyone to buy
a tool that produces such monsterous code, regardless of whether it was
'correct' or not.
Richard

I aready said this - when you open InitializeComponent method in any(!)
Windows.Forms or Asp.Net application you will see exactly the code that is
in the mentioned "monsterous method". I can give you a sample of that code:

this.txtAddress = new Xxx.Report.Components.XxxText();
this.txtAddress.ClientRectangle = new Xxx.Base.Drawing.RectangleD(0, 2.2,
9.8, 0.6);
this.txtAddress.Name = "txtAddress";
this.txtAddress.GetValue += new
Xxx.Report.Events.XxxGetValueEventHandler(this.txtAddress__GetValue);
this.txtAddress.Border = new
Xxx.Base.Drawing.XxxBorder(Xxx.Base.Drawing.XxxBorderSides.None,
System.Drawing.Color.Black, 1, Xxx.Base.Drawing.XxxPenStyle.Solid, false, 4,
new Xxx.Base.Drawing.XxxSolidBrush(System.Drawing.Color.Black));
this.txtAddress.Brush = new
Xxx.Base.Drawing.XxxSolidBrush(System.Drawing.Color.Transparent);
this.txtAddress.Font = new System.Drawing.Font("Arial", 9F);
this.txtAddress.TextBrush = new
Xxx.Base.Drawing.XxxSolidBrush(System.Drawing.Color.Black);
this.txtAddress.TextFormat = new
Xxx.Report.Components.TextFormats.XxxGeneralFormatService();
this.txtAddress.TextOptions = new Xxx.Base.Drawing.XxxTextOptions(false,
false, false, 0F, System.Drawing.Text.HotkeyPrefix.None,
System.Drawing.StringTrimming.None);

Just to give you an idea I should to say that this code initializes the
Report object. It was generated on reports definition. I mean - the tool
takes definitions and generates C# code that comply that definitions, after
that it compiles that code and run it to get the results. You perhaps heard
about the R# project? This is something alike...

The method became too big because the report definitions became more
complex - there are too many different objects on each page and number of
pages increasing. And it is sequent that with increasing complexity of such
definitions the size of generated code will be increased too. Then I could
not agree with your valuation of the "tool that produces such monsterous
code". Because I very happy that I found this tool. I tried some other
similar tools and select the best on my opinion. Also I wish to say - this
tool fits our needs for 99%, it has a perfect price, fast support team
reaction and so on...

And also please keep in mind - such methods (and mentioned monsterous method
too) do not contain local variables at all! Then, once again, - this is not
limitation of local variables! I think this is somethign other!...


WBR,
Dmitry.
 
Back
Top