I'm working with a C/Fortran library from C++ and the library calls exit(). I would like it to throw an exception so that the destructors in my C++ program will be called. I have been able to create my one definition of exit that throws an exception, but then terminate is still called. Is there to prevent terminate from being called and allow the normal exception handling to happen?
UPDATE: In the comments it was pointed out that this works on x64 but fails on x86, so the main question is "is there is a way to make x86 work like x64?".
UPDATE2: See my response about why this wasn't working on x86 and how to fix it.
Here's my test code:
test_exception.c
#include <stdlib.h>
void call_c() { exit(1); }
test_exception.cpp
#include <iostream>
#include <stdexcept>
extern "C" void call_c();
extern "C" void exit(int value)
{
throw std::runtime_error(std::string("Throwing an exception: ") + char('0' + value));
}
int main()
{
try {
call_c();
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Built with the following commands:
gcc -c test_exception.c -o test_exception_c.o
g++ -c test_exception.cpp -o test_exception_cpp.o
g++ test_exception_c.o test_exception_cpp.o -o test_exception
I understand you may not want to read this, but it's most likely a mistake to continue executing a program after any part of it has attempted to call exit()
or similar.
If part of the program called exit()
, you have no guarantees about the state of the program at that point. You don't know if the heap is in a consistent state. You don't know if the stack is any good. If you convert the exit()
into a throw
, the very least you're likely to encounter are memory leaks each time this happens. You don't know if the library that caused this error can be safely called again.
If you have inspected the library's source code, and you're certain that no corruption will result, then the cleanest solution would be to modify the library itself, so that it throws instead of exiting.
If changing the library is not permissible, the other clean and correct solution is to put all usage of the library into a separate process which you can monitor and restart.
The above code works, but on x86 before gcc 4.6, -fexceptions or -funwind-tables needs to be added when building the C code so that the stack unwinding can happen. You can see the details here.
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