1

Browsing through the MSDN, I found the following quote (emphasis mine):

OpCodes.Throw

Throws the exception object currently on the evaluation stack.

The stack transitional behavior, in sequential order, is:

  1. An object reference (to an exception) is pushed onto the stack.

  2. The object reference is popped from the stack and the exception thrown.

I cannot find anything about the case where the thrown exception is a stack overflow exception. How is this pushed onto the stack, when the stack is full?

Does the CLR always reserve at least some space for a StackOverflowException? Is it handled separately from all other exceptions? Are we even talking about the same stack here?

And why does it need to be pushed onto the stack in the first place, if it is immediately popped? Or is step 2 not done by the Throw opcode, but only when the exception is caught?

Is this documented somewhere (I would have expected it on the linked page).

CompuChip
  • 9,143
  • 4
  • 24
  • 48
  • 3
    The stack in question there is the evaluation stack, not the call stack. – Lee Dec 09 '15 at 21:59
  • It isn't pushed on to the stack. Memory is pre allocated for it. I know there is a stack overflow question that explains it, but I can't find it at the moment. – Bradford Dillon Dec 09 '15 at 22:03
  • @BradfordDillon probably, but I couldn't find it so I would very much appreciate it if you could. I did find this one - http://stackoverflow.com/a/22467611/2920343 - which also mentions a little bit about the process from the OS side. – CompuChip Dec 09 '15 at 22:08
  • @CompuChip You can check for yourself in Visual Studio 2015 if you have it installed. Make an empty console app and put a breakpoint. Take a memory snapshot using the diagnostic tools. Then look at the objects, and if you search both `StackOverflowException` and `OutOfMemoryException` are already allocated. I will continue to try to find the question I mentioned. – Bradford Dillon Dec 09 '15 at 22:10
  • Naturally, the StackOverflowException is thrown on this site, every time a stupid question is found ;-) – Dieter Meemken Dec 09 '15 at 23:58

1 Answers1

2
  OpCodes.Throw

That's an MSIL instruction, only ever generated when a program intentionally throws an exception. Produced by the throw keyword in C#. No program ever throws SOE, unless the programmer is on the right side of the Ballmer peak.

SOE is generated by the operating system, an SEH exception. It is the OS that can tell that a program is trying to scribble past the end of the allocated stack for a thread. Underlying OS feature is a guard page. The CLR dutifully intercepts it and translates it to a managed exception. Where it will end soon, SOE is an unrecoverable mishap and you'll only get a diagnostic in a console mode app. The thread is desperately out of stack space to do anything meaningful in managed code, it can't even reliably create the SOE object. Which is pre-allocated in the CLR, something you notoriously see back in memory profilers. Which answers your question.

Plenty more where that comes from, other very common exceptions that are generated by the OS and rare-to-never thrown by a program (MSIL) are NullReferenceException, DivideByZeroException, AccessViolationException, etcetera. All very nasty, never the kind you want to catch because you'd be hiding a programming bug.

There's a subclass of them, thrown by the CLR instead of the OS. It is a minor distinction, really, because the CLR is in effect the OS for a managed program. Common ones are OutOfMemoryException, ExecutionEngineException, TypeLoadException, MissingMethodException, etcetera. You never want to catch them either.


Long story short, program failure is not only reported by a compiled C# program. The operating system, the jitter and the CLR have reasons to complain as well.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks Hans, I don't have time to read the linked pages at the moment, but your answer looks complete and clearly identifies my misunderstanding! – CompuChip Dec 10 '15 at 09:19