【问题标题】:C++: Safe to use longjmp and setjmp?C++:使用 longjmp 和 setjmp 安全吗?
【发布时间】:2009-09-03 21:32:09
【问题描述】:

在 linux/gcc 上的 C++ 中使用 longjmp 和 setjmp 是否安全?

  1. 异常处理(我没有使用 longjmp/setjmp 实现异常处理。我想知道 longjmp/setjmp 会对标准异常处理产生什么副作用)
  2. *this指针
  3. 信号
  4. 智能指针(boost 的共享和侵入式指针)
  5. 你能想到的任何其他东西。

【问题讨论】:

    标签: c++ linux exception gcc setjmp


    【解决方案1】:

    setjmp()/longjmp() 完全颠覆了堆栈展开,因此也颠覆了异常处理以及 RAII(一般的析构函数)。

    从 18.7/4 标准中的“其他运行时支持”开始:

    如果任何自动对象将被抛出的异常转移销毁 控制到程序中的另一个(目标)点,然后在将控制转移到同一(目标)点的抛出点调用 longjmp(jbuf, val) 具有未定义的行为。

    所以底线是setjmp()/longjmp() 在 C++ 中表现不佳。

    【讨论】:

    • 你能解释一下 longjmp 是如何与显式内存删除和析构函数混淆的吗?
    • 通常,只要有某种方式可以退出 C++ 中的作用域(返回、抛出或其他),编译器将放置指令以调用 dtors 以获取任何需要销毁的自动变量离开那个街区。 longjmp() 只是跳转到代码中的新位置,因此它不会为调用 dtor 提供任何机会。该标准实际上没有那么具体——标准并没有说不会调用 dtors——它说所有的赌注都没有。在这种情况下,您不能依赖任何特定的行为。
    • 由于智能指针依赖于被销毁,你会得到未定义的行为。未定义的行为很可能包括引用计数未递减。使用longjmp() 是“安全的”,只要您没有将导致调用 dtor 的代码中的 longjmp 退出。然而,正如 David Thornley 在评论中指出的那样,即使在直接的 C 中正确使用 setjmp()/longjmp() 也可能很棘手——在 C++ 中它们是非常危险的。尽可能避免使用它们。
    • @jameszhao00:如果你对智能指针不够了解,(尽快熟悉它们)想想其他事情:std::vectorstd::string 不会释放它的内存,@987654332 @不关闭它的文件和类似的东西。
    • 您是否可以跟踪自调用 setjmp() 以来创建的所有对象,然后在调用 longjmp 时通过此列表调用析构函数?我知道您可以覆盖 new 以跟踪在堆上分配的所有对象,但是我目前不确定您将如何检测在堆栈上创建的对象。
    【解决方案2】:

    它并不特定于 Linux 或 gcc;如果您使用 longjmp 离开存在带有析构函数的自动变量的上下文,则 setjmp / longjmp 和 C++ 不能很好地协同工作。

    析构函数不会运行,这可能会导致内存泄漏或其他不良行为。

    【讨论】:

    • 微软记录了他们的 longjmp 实现破坏了词法范围的对象。我试过了,确实如此。非常好——我必须记得请求 GNU C 库允许你在跳转缓冲区上设置一个标志来做类似的事情。
    猜你喜欢
    • 2015-12-10
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2020-08-21
    • 2013-01-19
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    相关资源
    最近更新 更多