为什么.NET表现得如此之差,当StackOverflowException被抛出? [英] Why does .NET behave so poorly when StackOverflowException is thrown?

查看:108
本文介绍了为什么.NET表现得如此之差,当StackOverflowException被抛出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,在.NET StackOverflowExceptions不能被捕获,拿下他们的过程,并没有堆栈跟踪。这是官方记录 MSDN上。但是,我不知道什么技术(或其他方式)的原因是背后的行为。所有MSDN说的是:

I'm aware that StackOverflowExceptions in .NET can't be caught, take down their process, and have no stack trace. This is officially documented on MSDN. However, I'm wondering what the technical (or other) reasons are behind the behavior. All MSDN says is:

在.NET Framework的早期版本中,您的​​应用程序可以赶上   一个StackOverflowException对象(例如,从恢复   无限递归)。然而,这一做法目前正在劝阻   因为显著额外的code需要可靠地捕捉   堆栈溢出异常并继续执行程序。

In prior versions of the .NET Framework, your application could catch a StackOverflowException object (for example, to recover from unbounded recursion). However, that practice is currently discouraged because significant additional code is required to reliably catch a stack overflow exception and continue program execution.

什么这是显著额外的code?是否还有其他原因记录的这种行为?即使我们不能赶上国有企业,我们为什么不能至少可以得到一个堆栈跟踪?几个同事和我刚刚击沉几个小时到调试生产StackOverflowException将采取分钟堆栈跟踪,所以我不知道如果有一个很好的理由,我的痛苦。

What is this "significant additional code"? Are there other documented reasons for this behavior? Even if we can't catch SOE, why can't we at least get a stack trace? Several co-workers and I just sunk several hours into debugging a production StackOverflowException that would have taken minutes with a stack trace, so I'm wondering if there is a good reason for my suffering.

推荐答案

线程的堆栈是由Windows创建的。它采用所谓的保护页的是能够检测堆栈溢出。一个特点是在的这个MSDN库文章。的基本思路是,在最后两页叠层的(2×4096 = 8192字节)的保留的并给他们的任何处理器访问触发器真实变成一个SEH例外,STATUS_GUARD_PAGE_VIOLATION页错误。

The stack of a thread is created by Windows. It uses so-called guard pages to be able to detect a stack overflow. A feature that's generally available to user mode code as described in this MSDN Library article. The basic idea is that the last two pages of the stack (2 x 4096 = 8192 bytes) are reserved and any processor access to them triggers a page fault that's turned into an SEH exception, STATUS_GUARD_PAGE_VIOLATION.

这是通过在属于一个线程堆栈这些网页的情况下,内核截获。它改变了保护属性对于那些2页,从而使线程一些紧急的栈空间来处理事故,然后重新引发一个STATUS_STACK_OVERFLOW例外。

This is intercepted by the kernel in the case of those pages belonging to a thread stack. It changes the protection attributes for those 2 pages, thus giving the thread some emergency stack space to deal with the mishap, then re-raises a STATUS_STACK_OVERFLOW exception.

这异常依次由CLR截获。在这一点上有堆栈空间大约7千字节离开。这是一个,不足以运行刚刚在时间编译器(抖动)进行编译在code,可以应付异常在程​​序中,抖动需要更多的空间比。在CLR因此不能做任何事情,但粗暴地中止该线程。而通过.NET 2.0的政策也将终止该进程。

This exception is in turn intercepted by the CLR. At that point there's about 7 kilobytes of stack space left. This is, for one, not enough to run the Just-in-time compiler (JITter) to compile the code that could deal with the exception in your program, the JITter needs much more space than that. The CLR therefore cannot do anything else but rudely abort the thread. And by .NET 2.0 policy that also terminates the process.

这一个解释了为什么这不是在Java中的一个问题,它可以在没有即时编译却又如此有保证,可执行用户code可以运行跨preT字节code。或书面像C,C ++或Delphi,语言非管理程序code是在构建时生成。它仍然是一个的非常的硬伤很难对付,在堆栈中的紧急空间被烧断,所以没有方案中继续线程上运行code是安全的事情。一个程序可以继续使用一个线程终止在完全随机的位置,而损坏状态正常运行的可能性是不太可能。

This for one explains why this is not a problem in Java, it can interpret bytecode that isn't JITted yet so there's a guarantee that executable user code can run. Or in a non-managed program written in languages like C, C++ or Delp code is generated at build time. It is still a very difficult mishap to deal with, the emergency space in the stack is blown so there is no scenario where continuing to run code on the thread is safe to do. The likelihood that a program can continue operating correctly with a thread aborted at a completely random location and rather corrupted state is quite unlikely.

如果有任何努力都在考虑提高对另一个线程的事件,或在WINAPI去除限制(的保护页数,不可配置),那么这是任何一个非常良好的保密或只是没有认为有用。我怀疑是后者,不知道这是事实。

If there was any effort at all in considering raising an event on another thread or in removing the restriction in the winapi (the number of guard pages is not configurable) then that's either a very well-kept secret or just wasn't considered useful. I suspect the latter, don't know it for a fact.

这篇关于为什么.NET表现得如此之差,当StackOverflowException被抛出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆