【问题标题】:Is there a safe way to use setjmp() and longjmp() in C++?有没有在 C++ 中使用 setjmp() 和 longjmp() 的安全方法?
【发布时间】:2011-03-27 11:24:45
【问题描述】:

我的印象是,在 C++ 中使用 setjmp()longjmp() 几乎肯定会弄乱堆栈,因为这些函数不会像异常那样执行展开。但是,This MSDN page 表明可以告诉 Microsoft 实现调用本地对象的析构函数,这意味着谨慎使用这些函数可能是安全的。

在 C++ 中使用 setjmp()longjmp() 时,是否有可移植的方法来确保程序的正确性? C++ 的最佳实践表明,最好不要将异常用于流控制,但在需要非常不寻常的流的情况下(例如,协程和闭包),总是最好使用异常来代替这些函数吗?

【问题讨论】:

  • 协程见[如何在C++中实现协程](stackoverflow.com/questions/121757/…)。
  • “在需要非常不寻常的流程的情况下”,最好问问如何实现那个特定的不寻常的工作流程。抽象问题很少有有用的答案。
  • @Dummy00001:我通过提供不寻常的控制结构的例子来泛指setjmp()/longjmp()的各种用途,而不是试图暗示我在做其他类型的流量控制黑魔法。我只是问是否有一种在 C++ 中使用这些函数的安全方法,我得到了答案。

标签: c++ exception coroutine


【解决方案1】:

如果您有一些非常奇怪的要求,不允许您通过条件/循环/中断来正常控制程序的流程,我更愿意使用 jmp 异常。

在某些情况下,使用异常来控制流是可以接受的。我认为 Boost.Graph 的其中一个搜索函数会抛出异常以从深度递归中快速返回给调用者。

【讨论】:

  • 那么,我更喜欢例外。不过,我仍然想知道是否有可能摆脱*jmp()
  • 不,不可能在保持便携性的同时做到这一点。我刚刚在 Windows 上使用 Visual Studio 和 Linux 上使用 gcc 进行了测试。 VS 实现正确地调用了析构函数。 gcc 实现不会破坏从堆栈中删除的对象。
  • 我曾经在一个旧的 C 库周围创建一个包装器(不记得是哪个);这个库要求我传递回调函数,以及该库的某些部分(我在回调中调用)使用 longjmp。这是我希望我永远不必调试的那种代码
【解决方案2】:

我以前使用过它们,但只是在一种情况下:我正在用 C 语言为一个 OS 类创建一个 OS 内核;它们用于异常处理。

我的理解是,它们用于处理低级代码(如操作系统)时的异常处理。对于一般的 C++ 软件,我会使用 try catch

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 2013-01-19
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    相关资源
    最近更新 更多