gpt4 book ai didi

c# - 为什么 .NET 在抛出 StackOverflowException 时表现如此糟糕?

转载 作者:IT王子 更新时间:2023-10-29 03:45:40 25 4
gpt4 key购买 nike

我知道 .NET 中的 StackOverflowExceptions 无法被捕获、取消其进程并且没有堆栈跟踪。这是官方记录的 on MSDN .但是,我想知道这种行为背后的技术(或其他)原因是什么。 MSDN 所说的是:

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.

这个“重要的附加代码”是什么?这种行为是否有其他记录在案的原因?即使我们抓不到 SOE,为什么我们至少不能得到堆栈跟踪?我和几位同事刚刚花了几个小时来调试生产 StackOverflowException,如果使用堆栈跟踪可能需要几分钟,所以我想知道我的痛苦是否有充分的理由。

最佳答案

线程的栈是由Windows创建的。它使用所谓的保护页面 来检测堆栈溢出。 this MSDN Library article 中描述的用户模式代码通常可用的功能.基本思想是堆栈的最后两页(2 x 4096 = 8192 字节)保留,任何处理器访问它们都会触发页面错误,该错误会变成 SEH 异常,STATUS_GUARD_PAGE_VIOLATION。 p>

在属于线程堆栈的那些页面的情况下,这被内核拦截。它更改了这 2 个页面中第一个页面的保护属性,从而为线程提供了一些紧急堆栈空间来处理事故,然后重新引发 STATUS_STACK_OVERFLOW 异常。

此异常又被 CLR 拦截。那时还剩下大约 3 KB 的堆栈空间。一方面,这不足以运行 Just-in-time编译器 (JITter) 来编译可以处理程序中异常的代码,JITter 需要比这更多的空间。因此,CLR 只能粗鲁地中止线程,不能做任何其他事情。并通过 .NET 2.0 策略也终止该进程。

请注意,这在 Java 中问题不大,它有一个字节码解释器,因此可以保证可执行的用户代码可以运行。或者在用 C、C++ 或 Delphi 等语言编写的非托管程序中,代码是在构建时生成的。然而,这仍然是一个非常难以处理的事故,堆栈中的紧急空间已用完,因此没有任何情况可以安全地继续在线程上运行代码。当一个线程在一个完全随机的位置中止并且处于损坏状态时,程序可以继续正确运行的可能性很小。

如果有任何努力考虑在另一个线程上引发事件或删除 winapi 中的限制(保护页面的数量不可配置)那么这要么是一个非常保守的 secret ,要么就是不是认为有用。我怀疑是后者,不知道是不是事实。

关于c# - 为什么 .NET 在抛出 StackOverflowException 时表现如此糟糕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22465541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com