C语言中使用setjmp和longjmp在链接C++库时的用法

6
我希望您能在链接到使用C++实现的库(但具有C API)的C程序中使用setjmp和longjmp。
虽然C++代码确实进行了动态内存分配,并且指针通过API传递,但只要C端正确地管理这些(不透明的)对象,那么在使用longjmp时就不应该出现任何问题,对吗?
我知道在C ++代码中使用这些函数是不安全的,但在链接到C ++代码的C代码中使用它们是否安全?
3个回答

4

你从C代码中调用C++函数并不会使setjmp和longjmp比它们本来更加不安全。

重要的是,如果你的库分配了资源,你必须编写恢复代码以确保在调用longjmp后这些资源被正确释放。虽然对于你自己的分配来说这可能很容易,但根据你使用的C接口如何结构化,对于C++库来说可能会很难或不可能实现。


好的。我的想法是,只要C++库中进行的那些分配可以通过适当的C接口调用进行清理,那么C++代码就与longjmp的影响隔离开来,异常处理和longjmp也不会相互干扰。(我也是C++库的实现者。) - Posco Grubb
如果在C++库中有异常处理,您应确保任何抛出的异常都被捕获在库内部,您不希望异常逃出您的C++代码(不确定如果这样做会发生什么,从未尝试过)。对于释放C++分配,您将需要弄清楚在longjmp调用之后控制权交给C代码时需要释放什么。由于您拥有应用程序和库,我认为没有任何问题可以使其正常工作。 - Miguel Grinberg

2

setjmp/longjmp 在 C++ 中一般不安全。它们实际上复制了异常的行为,但是没有正确地展开堆栈(例如,它们不会运行被强制退出的堆栈帧上的对象的析构函数)。如果可能的话,请改用异常。


OP并不是在尝试在C++中使用setjmp/longjmp,而是一个使用C接口的C程序,该程序通过一些C ++代码(可以被调用为C的代码)来使用一些C ++代码,这样做是安全的。 - Chris Lutz
2
即使如此,这也取决于情况。在您自己的代码中跳转可能是安全的,但使用longjmp退出回调函数(例如)可能会造成混乱。 - user149341
在任何语言中,使用longjmp退出回调(除非明确获得许可)听起来都是一个坏主意。在C语言中,你也必须自己清理好内存。 - Chris Lutz
@duskwuff 好的,在回调中使用它是危险的,但如果我没有混合语言,那就是这种情况。除此之外,还有其他任何情况让你说“这要看情况”? - Posco Grubb

1

嗯,对也不对。通常情况下,longjmp 不会调用析构函数,因此在像以下代码这样的代码中使用它:

void f(jmp_buf jb)
{
  some_cpp_object_with_a_nontrivial_destructor x;
  if (some_condition) longjmp(jb, 2);
  // some other code
}

会导致各种糟糕的情况发生。如果避免这些情况,你应该没问题。(通常情况下,longjmp 不得跨越具有非平凡析构函数的对象的任何活动堆栈帧。)


我的代码是C,所以我不能定义具有构造函数的类型的局部变量。因此,你的例子对我的问题不适用。 - Posco Grubb
如果您给C++函数一个回调,而该回调调用longjmp,则最终会出现非常相似的情况。 - zvrba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接