StackOverflowException在哪里创建?

时间:2015-12-09 21:55:04

标签: c# stack-overflow throw opcode

浏览MSDN,我发现了以下quote(强调我的):

  

OpCodes.Throw

     

抛出当前在评估堆栈上的异常对象。

     

堆栈过渡行为按顺序排列:

     
      
  1. 对象引用(异常)被压入堆栈

  2.   
  3. 从堆栈中弹出对象引用并抛出异常。

  4.   

我找不到任何关于抛出异常是堆栈溢出异常的情况。当堆栈装满时,它是如何被压入堆栈的?

CLR是否始终为StackOverflowException保留至少一些空间?它是否与所有其他例外分开处理?我们在这里甚至谈论相同的堆栈吗?

如果它立即弹出,为什么首先需要将它推入堆栈?或者,第2步不是由Throw操作码完成的,而是仅在捕获到异常时才执行?

这是在某处记录的(我希望在链接页面上预期)。

1 个答案:

答案 0 :(得分:2)

  OpCodes.Throw

这是一条MSIL指令,仅在程序故意引发异常时生成。由C#中的throw关键字生成。除非程序员在鲍尔默峰的右侧,否则没有程序会抛出SOE。

SOE由操作系统生成,即SEH例外。操作系统可以告诉程序正在尝试在线程的已分配堆栈的末尾划线。底层操作系统功能是guard page。 CLR尽职尽责intercepts it并将其转换为托管例外。即将结束的地方,SOE是一个不可恢复的事故,您只能在控制台模式应用程序中获得诊断。线程拼命地离开堆栈空间以在托管代码中执行任何有意义的操作,甚至无法可靠地创建SOE对象。这是在CLR中预先分配的,这是你在内存分析器中众所周知的。哪个回答你的问题。

来自的地方还有很多,操作系统生成的其他常见异常以及程序(MSIL)难以抛出的异常是NullReferenceException,DivideByZeroException,AccessViolationException等。所有非常讨厌,从来没有你想要捕获的那种,因为你将隐藏编程错误。

它们有一个子类,由CLR而不是操作系统抛出。实际上,这是一个次要的区别,因为CLR实际上是托管程序的操作系统。常见的有OutOfMemoryException,ExecutionEngineException,TypeLoadException,MissingMethodException等。你永远也不想抓住他们。

长话短说,程序失败不仅仅是由编译的C#程序报告的。操作系统,抖动和CLR也有理由抱怨。