I created app with following code (just for research purposes):
using System; using System.CodeDom; using System.Linq; using System.Reflection; using System.Security.Permissions; namespace HelloWorld { public class Program { static Program() { throw new Exception("Here we are"); } static void Main(string[] args) { Console.WriteLine("Hello, world!"); } } }
I expect that I would have a TypeInitializationException
exception here before calling the Main()
method because a static ctor must be called only once and just before first calling of any member of this class. So, in this case, CLR has to call static ctor for the Program class and after that it has to call the Main()
method. But here is one strange thing: this exception is thrown from the Main()
. But why? We should have the exception from another place because Main can't be invoked.
Here is exception message:
Unhandled Exception: System.TypeInitializationException: The type initializer for 'HelloWorld.Program' threw an exception. ---> System.Exception: Here we are at HelloWorld.Program..cctor() in D:\research\HelloWorld\Program.cs:line 13 --- End of inner exception stack trace --- at HelloWorld.Program.Main(String[] args)
Update:
I have this message.
Unfortunately I can't debug app after this exception.
- The main method should simply terminate if any exception occurs. The throws clause only states that the method throws a checked FileNotFoundException and the calling method should catch or rethrow it. If a non-checked exception is thrown (and not catch) in the main method, it will also terminate.
When an exception occurred, if you don't handle it, the program terminates abruptly and the code past the line that caused the exception will not get executed.
2) There is a special catch block called the 'catch all' block, written as catch(…), that can be used to catch all types of exceptions. For example, in the following program, an int is thrown as an exception, but there is no catch block for int, so the catch(…) block will be executed.
It's not specific to Main
entry point method. Consider this code:
public class Program { static void Main(string[] args) { MyClass.Test(); } } static class MyClass { static MyClass() { throw new Exception("here we are"); } public static void Test() { Console.WriteLine("test"); } }
If you run it, exception stack trace will be:
Unhandled exception: System.TypeInitializationException: Type initialized for "ConsoleApp2.MyClass" threw an exception. ---> System.Exception: here we are
at ConsoleApp2.MyClass..cctor()
--- End of inner exception stack trace ---
at ConsoleApp2.MyClass.Test()
at ConsoleApp2.Program.Main(String[] args)
So, the same situation as with exception in static constructor of entry point class.
If you run that application with WinDbg and run !clrstack
when exception is thrown, you will see:
000000af568fdc98 00007ffd54659d98 [GCFrame: 000000af568fdc98]
000000af568fde58 00007ffd54659d98 [GCFrame: 000000af568fde58]
000000af568fea00 00007ffd54659d98 [PrestubMethodFrame: 000000af568fea00] ConsoleApp2.MyClass.Test()
000000af568febe0 00007ffce37704a2 ConsoleApp2.Program.Main(System.String[])
000000af568fee40 00007ffd42d86793 [GCFrame: 000000af568fee40]
And in stack window you can see:
clr!MethodTable::DoRunClassInitThrowing + 0x599
clr!MethodTable::CheckRunClassInitThrowing + 0xbb
clr!MethodDesc::DoPrestub + 0xd1d
When exactly to call static type constructor is determined by JIT compiler. When type explicitly defines static constructor, C# compiler will not mark type with BeforeFieldInit flag. Types with that flags are allowed to be initialized in "relaxed" fashion, at some point before their members are accessed (or at least before their static fields are accessed). So for them, JIT might emit static constructor call at any point before you access them, even right on startup of your application. Types without that flag are initialized in "precise" fashion - JIT will emit call to static constructor for them right when some member is accessed for the first time.
JIT performs compilation of methods on the fly. If method is not yet compiled into native code - method will point to a "stub". This stub contains code to run JIT, inspect method, compile it into native code, and then change method pointer from stub to compiled native code, so that on next call to this method flow goes directly to compiled code, without stub.
As you can see from WinDbg output - when exception happens, we are in a stub of MyClass.Test()
method. At this point, when performing compilation of MyClass.Test()
into native code, JIT sees that static constructor has not been run, emits code to call static constructor and compiles MyClass.Test()
. But all this happens after method is technically called (but before any code from that method has actually been executed), so it appears on call stack.
I've used different code to illustrate it's not related to Main
, but situation with code from your question is the same:
0000007ba0b3dba8 00007ffbfbb89d98 [GCFrame: 0000007ba0b3dba8]
0000007ba0b3dd68 00007ffbfbb89d98 [GCFrame: 0000007ba0b3dd68]
0000007ba0b3e910 00007ffbfbb89d98 [PrestubMethodFrame: 0000007ba0b3e910] ConsoleApp2.Program.Main(System.String[])
0000007ba0b3ed20 00007ffbfbb89d98 [GCFrame: 0000007ba0b3ed20]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With