2011-08-31 79 views
5

我想在C程序中使用setjmp和longjmp,该程序链接到使用C++实现的库(但具有C API)。使用C语言中的setjmp和longjmp链接到C++库时

C++代码确实做动态内存分配,并且指针通过API传递,但只要代码的C端正确管理那些(不透明)对象,在使用longjmp时不应该有任何混乱,对?

我知道在C++代码中使用这些函数并不安全,但是应该在C代码中安全吗?

回答

3

从C代码中调用C++函数并不会使setjmp和longjmp比以往更加不安全。

重要的是,如果你的库分配资源,你必须有适当的恢复代码以确保在调用longjmp之后这些代码被正确释放。虽然这对您自己的分配很容易,但根据您使用的C接口的结构,C++库可能很难或不可能。

+0

好的。我的想法是,只要通过适当的C接口调用清理C++库中的分配,C++代码就可以与longjmp的效果隔离开来,异常处理和longjmp不会干扰每个其他。 (我也是C++库的实现者)。 –

+0

如果你在C++库中有异常处理,你应该确保任何抛出的异常在库中被捕获,你不希望异常使它超出你的C++代码(不知道如果你这样做会发生什么,从来没有尝试过)。并且为了释放C++分配,你必须弄清楚在longjmp调用之后需要控制的C代码需要释放什么。既然你拥有应用程序和库,我没有看到任何问题来完成这项工作。 – Miguel

2

setjmp/longjmp通常是而不是可以安全地用于C++。它们有效地复制异常的行为,但不正确地展开堆栈(例如,它们不会为在堆栈框架上强制退出的对象运行析构器)。如果可能的话,如果你有它们,则使用异常。

+0

OP并没有试图在C++中使用'setjmp' /'longjmp',而是通过C接口使用一些C++代码的C程序(它可能将所有C++代码掩码为C调用的代码,并且这样做安全)。 –

+2

即使如此,它依赖于。在自己的代码中跳转可能是安全的,但使用'longjmp'退出回调(例如)可能会造成严重破坏。 – duskwuff

+0

使用'longjmp'来退出回调(除非明确给出了这样的权限),不管语言如何,听起来都是一个坏主意。你也必须在C后清理自己。 –

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不得跳过任何活动堆栈帧与对象具有非平凡的析构函数。)

+0

我的代码是C,所以我不能用具有构造函数的类型定义局部变量。因此你的例子不适用于我的问题。 –

+0

如果您给C++函数一个回调,并且回调函数调用longjmp,那么最终会出现类似的情况。 – zvrba