问题标签 [stack-unwinding]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - C++ 从析构函数中抛出异常
这不是关于从析构函数中抛出异常是否安全的问题。
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9状态:
“在堆栈展开期间,所有这些堆栈帧中的所有本地对象都被破坏了。如果其中一个析构函数抛出异常(比如它抛出一个 Bar 对象),C++ 运行时系统处于无赢的境地:它是否应该忽略Bar and end up in the } catch (Foo e) { 它原来的方向?它应该忽略 Foo 并寻找一个 } catch (Bar e) { 处理程序吗?没有好的答案——任何一个选择都会丢失信息。
IE:如果在堆栈展开期间抛出另一个异常,则运行时系统处于无赢状态,因为要“查找”的 catch 处理程序不明确。
当堆栈展开期间引发的异常位于 try/catch 块中时,上述情况是否存在“异常”?在这种情况下,没有歧义:
以下暗示了这一点,但我想知道是否有人知道相关的 C++ 标准部分。
“如果在堆栈展开期间析构函数抛出异常并且未处理该异常,则调用 terminate() 函数。以下示例演示了这一点:”
c - 如何在 SIGSEGV 上使用 _Unwind_Backtrace 获取 fullstacktrace
我通过代码处理 SIGSEGV:
处理程序代码在哪里:
但是 trace_func 仅调用一次,并且仅在 _Unwind_Backtrace 调用时显示。是否可以使用 _Unwind_Backtrace 获取导致 SIGSEGV 信号的代码的堆栈跟踪?
谢谢
mips - SIGSEGV 上的 mips _Unwind_Backtrace
在 mips 平台上,我试图让 Unwind 工作。目前,如果我手动发出 print_trace,堆栈跟踪将正确显示如下:
backtrace_helper 0x4b6958
backtrace_helper 0x4b6ab4
backtrace_helper 0x2ac2f628
获得 3 个堆栈帧。
./v(print_trace+0x38) [0x4b6958]
./v(main+0x90) [0x4b6ab4]
/lib/libc.so.0(__uClibc_main+0x24c) [0x2ac2f628]
但是当发生 SIGSEGV 时,堆栈跟踪不会显示正确的函数调用顺序。
backtrace_helper 0x4b7a74
backtrace_helper 0x2ab9b84c
获得 2 个堆栈帧。
./v(getLineIDByPhyIdx+0x3d8) [0x4b7a74]
/lib/libpthread.so.0(__new_sem_post+0x2c8) [0x2ab9b84c]
我正在使用 -g -fexceptions -rdynamic 进行编译。我还看到了当我的 gcc C++ 应用程序崩溃时如何生成堆栈跟踪,其中第二个答案提到了错误的地址,但是当我像他一样设置但它只更改第二帧并且其余部分相同时,代码片段如下:
代码:
php - PHP 类构造函数中的范围展开
我正在学习 PHP 类和异常,并且来自 C++ 背景,以下内容让我觉得很奇怪:
当派生类的构造函数抛出异常时,基类的析构函数似乎没有自动运行:
这打印:
另一方面,如果构造函数(at )中存在异常,则成员对象的析构函数会正确执行。#1
现在我想知道:如何在 PHP 的类层次结构中实现正确的范围展开,以便在发生异常时正确销毁子对象?
此外,似乎没有办法在所有成员对象都被销毁(at )之后#2
运行基本析构函数。也就是说,如果我们删除 line #1
,我们会得到:
如何解决这个问题?
更新:我仍然愿意接受进一步的贡献。如果有人有充分的理由说明为什么 PHP 对象系统从不需要正确的销毁序列,我将为此提供另一个赏金(或只是为任何其他令人信服的争论答案)。
c++ - 如何在析构函数期间检测异常是否处于活动状态?
在 C++ 中,如何在析构函数的主体中检测堆栈是否由于抛出异常而被展开?一旦检测到,我可以获得对活动异常的引用吗?
我问是因为我想添加一些调试代码来解释为什么会出现某种情况以及是否是由于异常引起的。
c++ - 为什么在 main 中没有捕获异常时不调用析构函数?
我有以下代码:
我看到一组~Foo()
执行时有try{} catch{}
块。当没有异常处理程序时,不会打印任何内容。这是否意味着在处理异常时调用堆栈分配对象的析构函数?还是因为 std::cerr 缓冲问题而没有打印任何内容?
c++ - 我不应该在线程过程中使用 _endthreadex() 进行堆栈展开吗?
我检查了有关 win32 环境中线程过程的堆栈展开。
我的测试代码如下。
输出结果:
dummy ctor
dummy ctor
dummy ctor
dummy dtor
bad allocation
dummy dtor
如您所知,构造函数和析构函数的输出不是配对的。我认为 _endthreadex() 使线程句柄发出信号并跳过线程的堆栈展开。
当我在没有 _endthreadex() 的情况下再次测试时,我能够得到我期望的结果。
在这种情况下,如果我需要在线程上展开堆栈,我不应该在线程过程中使用 _endthreadex() 吗?
c++ - 是否有任何方法导致 C++ 中的整个堆栈帧展开?(使用异常除外)
我一直在写一个延续 - 具体来说,协程 - 库。它类似于 std::thread (除了它是协作的) - 每个执行上下文都在延续对象中表示。
问题是关于延续对象的破坏。如果在执行上下文没有正常退出的情况下调用了延续对象的 dtor,它应该被销毁对象的上下文强制关闭。
这样,堆栈帧中的每个 C++ 对象都不会被正确销毁。这对任何人来说都可能不是一个愉快的情况——所以我决定找到一个解决方案。
第一次,我想使用异常来展开堆栈帧,如下所示。(请注意,下面只是有缺陷的伪代码。)
但是,我发现了一些严重的缺陷。任何如下“吞下异常”的用户代码都将完全打破协作调度的假设。
所以我需要找到其他方法来调用堆栈展开(或任何其他方式来破坏堆栈对象的延续)。标准一致性方式会很好 - 但延续实现本身依赖于平台特定的 API,因此不可移植的方式是可以接受的。(我用的是win32)
c# - x64 和 x32 中的不同行为展开堆栈
为什么在下面详述的场景中,堆栈空间在 x64 中增加但在 x32 中使用相同代码减少?
背景:
我们的客户可以使用领域语言编写脚本,该脚本在运行时使用递归技术进行解释并在 Web 服务器上执行。他们可能会在引发异常的脚本中出错,这个异常被捕获并记录下来。
由于这种递归技术,我们通过检查解释器执行脚本时使用的堆栈空间来防止堆栈溢出异常,并在我们实际用完堆栈之前终止脚本。
在 32 位模式下,一切正常,当脚本编写者出错Exception
并生成错误时,它会被记录,堆栈展开,在此期间堆栈上剩余的空间会增加,并且脚本会很好地终止。
在 64 位模式下,一切都不是那么好,当脚本编写者出错Exception
并生成错误时,它会被记录下来,堆栈展开,在此期间堆栈上剩余的空间会减少。这是非常糟糕的,因为如果脚本碰巧使用了大量的堆栈空间并抛出异常,那么展开堆栈并记录错误本身的行为可能会导致StackOverflowException
隐藏原始异常、阻塞 IIS 并杀死所有飞行中的请求(糟糕、非常糟糕和非常糟糕)。
重现问题:
这是一个控制台应用程序,它对我在生产中使用的代码进行建模,并在设置为 x64 时重新创建问题,并且在 x32 中运行良好。
示例输出:
x32 - 一切都是花花公子,堆栈空间随着下降而减少,并在展开期间增加。
这是 x64 中具有完全相同代码的输出,堆栈空间在下降时增加,但在展开期间继续减少:
奇怪的是,如果我删除“Catch”然后在 64 位下它保持堆栈使用相同 - 但我不能在生产中这样做,因为我需要登录 catch。
signals - 是否有 hpux _UNW_STACK_TRACE 堆栈展开函数的信号安全版本?
奇怪的是,hpux unwind API _UNW_STACK_TRACE不采用文件描述符,而是采用FILE*
. 较新的 APIuwx_stack_trace
也采用FILE*
.
由于这两个都使用缓冲 IO 而不是(信号安全 IO 接口)open
// write
,close
因此它们都不能安全地用于信号处理程序(这是人们希望这样做的最明显的地方之一)。
在我们的一个(可能现在已经死掉的)ia64 平台上,我们曾经有自己的 unwind 实现,但它是一个难以维护和易碎的野兽,所以我不想再走那条路了。HPUX 堆栈展开还有其他选项吗?