MORE INFORMATION
A program that is written in a .NET language, such as Visual Basic, C#, or Eiffel, is translated into Microsoft Intermediate Language (MSIL) instructions, which are stored in the output assembly. When you run the program, .NET compiles the MSIL instructions into equivalent native code such as Pentium instructions. A just-in-time (JIT) compiler performs this final translation on demand, just before each method executes.
In very rare circumstances, a language compiler may produce invalid MSIL. For example, the compiler may perform one of the following errors:
- Issue a value that has no matching MSIL instruction.
- Attempt to branch into the middle of another multibyte instruction.
- Attempt to create more local variables than .NET supports (32767).
When the invalid code runs, the JIT compiler detects the error, and then throws an InvalidProgramException. In some situations, the JIT compiler may throw this exception incorrectly, if the compiler determines that a method contains invalid MSIL.
When the program runs, and attempts to execute the code path that contains invalid instructions, the program will throw an InvalidProgramException.
Note If the program runs and does not encounter the invalid code path (for example, the invalid code path lies within an else block that is not used during this run), the program does not throw an exception. You are not informed that the problem exists until the program attempts to use the invalid code.
When the program throws the InvalidProgramException, a dialog box appears that provides you with the option to attach a debugger to examine the problem. You also have a choice of which debugger to use. To determine the location of the error, follow these steps:
- Click Yes, and then click to select New instance of Microsoft Development Environment.
- When the IDE appears, you receive another message box that reports the unhandled InvalidProgramException. Click Break.
- Open the call stack debug window to see the name of the method, and the line number, that contains the error.
How to troubleshoot the InvalidProgramException
To determine whether your assembly contains invalid MSIL, run the PEverify tool over your program. This tool performs a detailed analysis of all of the metadata and MSIL within the assembly, and then reports any problems. A typical problem report resembles the following:
[IL]: Error: [c:\MyApp\Prog.exe : MyClass::MethodX] jmp / exception into the middle of an instruction
- If PEverify locates invalid MSIL, then the language compiler that you used to build your application probably contains a bug. Please send a bug report to your compiler vendor.
- If your assembly passes the PEverify tool, then the .NET JIT compiler may contain a bug. Please send a bug report about this problem.
Note If your assembly contains unverifiable code, PEverify also reports every instance of unverifiable code. For example, this behavior occurs if you use the
unsafe option in C#, or if you use the compiler for Managed Extensions for C++. You must examine all of the instances of unverifiable code to find the instances that lead to an InvalidProgramException. A list of these instances appears at the end of this article, under the heading "PEverify messages that generate a runtime InvalidProgramException."
How to work around the problem
There is no specific solution for this problem. However, you can try various approaches to determine which method works best in a particular situation.
Try to rebuild your application with a nonoptimized version of the module that appears to contain the problem. How to do this depends on the programming language that you use, but typically corresponds to a
debug configuration build, or to a
/debug option on the command line.
Check the rebuilt application with PEverify. If the problem persists, try to make small changes to the method that is broken. You can add an extra local variable, or you can rearrange the code.
Note If you make changes to the code, be sure to preserve the correct algorithm. For example, use
if/else rather than the
?: construct.
Tips and tricks
It is possible that your application runs properly when you build the application with optimizations turned off, such as in a debug configuration. But your application throws an InvalidProgramException when you build the application with optimizations turned on, such as in a retail configuration. If you attempt to investigate this behavior by running the application from the Visual Studio .NET IDE, the problem does not appear.
The problem does not occur when you run a program from within the Visual Studio debugger because the debugger assumes that you want to debug the program and instructs the JIT compiler not to optimize. To run the application with the JIT compiler optimized, build the program in retail configuration, and then launch the program outside of the Visual Studio debugger. You can double-click the program file name in Explorer or run the program from the command line.
When you have narrowed down the location in your code where the problem may exist, you can JIT-attach a debugger to run before the program reaches the line that throws the InvalidProgramException. Insert a call to
System.Diagnostics.Debugger.Break in your code at the point where you want to inspect the program.
If the InvalidProgramException occurs only on retail builds, you can use CorDbg, the command-line debugger that ships with the .NET Framework SDK, which can debug fully-optimized code. Type
CorDbg, and then type
mode jit 1 to enable JIT optimizations. Then you can run your application with ( run
MyApp ), set breakpoints, inspect source, show the native-generated code, dump memory, and so forth.
If you write a program in raw MSIL, and use the ILASM assembler tool to build the program into an assembly, always run the PEverify tool over the assembly to check for mistakes. ILASM was designed for advanced users of the .NET platform, such as compiler writers. This assembler tool runs "with the guards off," and deliberately enables you to generate invalid MSIL. This behavior is useful when you write test software to check runtime behavior. For example, you can insert an instruction that is likely to throw an InvalidProgramException, such as the following:
br -3
You can also use the
.emitbyte directive to achieve similar, nontypical behavior.
PEverify messages that generate a runtime InvalidProgramException
The following PEverify messages indicate that an InvalidProgramException will be thrown at runtime, which indicates that your language compiler probably contains a bug.
Note This list includes only the message text. The actual report contains more detailed information about where the error is located.
Unknown opcode.
Unknown calling convention.
Unknown ELEMENT_TYPE.
Stack is too large.
fall thru end of the method.
try start >= try end.
try end > code size.
handler >= handler end.
handler end > code size.
filter >= code size.
Try starts in the middle of an instruction.
Handler starts in the middle of an instruction.
Filter starts in the middle of an instruction.
Try block overlap with another block.
Try and filter/handler blocks are equivalent.
Try shared between finally and fault.
Handler block overlaps with another block.
Handler block is the same as another block.
Filter block overlaps with another block.
Filter block is the same as another block.
Filter contains try.
Filter contains handler.
Nested filters.
filter >= code size.
Filter starts in the middle of an instruction.
jmp / exception into the middle of an instruction.
Unrecognized local variable number.
Unrecognized argument number.
Code size is zero.
Method ends in the middle of an instruction.
Branch out of the method.
Finally handler blocks overlap.
Lexical nesting.
Innermost exception blocks should be declared first.
filter block should immediately precede handler block.