In C++, when working with a C library which uses longjmp
for error handling. Is it safe to have the C code jump into C++ using setjmp
. I know that jumping away from C++ code can lead to issues with destructors not being called but is the same true for jumping into C++ code.
Pseudo code of usage
if( setjmp( lib_get_jmpbuf() ) )
{
throw "exception";
}
if( lib_question() )
{
std::vector<int> stuff(5);
lib_could_jump_way(stuff.data(), stuff.size());
}
If this is not safe, how do you interface with such C libraries safely?
As your sample is written, the library code could jump back into a different scope than the one from which it's called. And since the stuff
vector is in that scope, I wouldn't expect it to be destroyed when the exception is thrown. (Stack unwinding for exception propagation is complex, so I could be wrong.)
At a minimum, I'd hoist stuff
above the setjmp()
.
A better idea might be to create a C wrapper function for each library API that might throw. The wrapper should be responsible for the setjmp
. Whether the library function returns or jumps, the wrapper should convert the result to a regular return. The C++ code then would call the wrapper function and either proceed or throw based on the return value.
// wrapper.c (should be compiled as C, not C++)
#include "wrapper.h"
int lib_could_jump_wrapper(int *stuff, size_t size) {
if (setjmp(lib_get_jmp_buf())) {
return LIBRARY_JUMPED;
}
lib_could_jump_way(stuff, size);
return LIBRARY_RETURNED;
}
// wrapper.h
#define LIBRARY_RETURNED 0
#define LIBRARY_JUMPED 1
#ifdef __cplusplus__
extern "C" {
#endif
int lib_could_jump_wrapper(int *stuff, size_t size);
#ifdef __cplusplus__
}
#endif
// Your C++ code:
#include "wrapper.h"
// ...
if (lib_question()) {
std::vector<int> stuff;
if (lib_could_jump_wrapper(stuff.data(), stuff.size()) == LIBRARY_JUMPED) {
throw "exception"
}
// ...
}
The problem with longjmp
into C++ is the same as the problem with longjmp
out of C++: some destructors might not get run when they should have. In your example code, the vector<int>
will probably be leaked if the library calls longjmp.
If you control all the C++, you can arrange things so the longjmp never bypasses any destructors. Adrian McCarthy's answer demonstrates how.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With