Re: What should happen with an exception in mixed C/C++ code?
Bjorn Reese wrote:
Mehturt@gmail.com wrote:
As I have discovered by other posters it's an undefined behavior, I'm
using something similar with gcc, but the C code must be compiled with
-fexceptions, so you might have a look at this..
You may still leak resources in the C code.
Yes, but if the C code does not expect the callback to return control
(e.g. it is error handler which by default outputs a error message and
calls exit()) you may use setjmp/longjmp to return to your C++ code and
throw exception from there. Also, you do not have to compile with
-fexceptions. For example (rough code, not tested):
/* C code */
/* lib.h */
struct lib
{
/*...*/
void (*on_error)(struct lib*, char const*);
};
#ifdef __cplusplus
#define EXTERN extern "C"
#else
#define EXTERN extern
#endif
EXTERN void lib_init(struct lib*);
EXTERN void lib_do_something(struct lib* lib);
/* lib.c */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "lib.h"
static void
on_error_exit(struct lib*, char const* message)
{
fputs(message, stderr);
exit(EXIT_FAILURE);
}
void
lib_init(struct lib* lib)
{
/*...*/
lib->on_error = on_error_exit;
}
void
lib_do_something(struct lib* lib)
{
/*...*/
lib->on_error(lib, "error occured");
assert(0); /* should never get here */
}
// C++ code
#include <setjmp.h>
#include <stdexcept>
#include "lib.h"
// "subclass" lib struct
struct lib_ext
{
struct lib lib;
jmp_buf jmpbuf;
char const* last_error; // for simplicity; std::string might be
used
lib_ext(void);
void do_something(void);
static void on_error(struct lib_ext* lib, char const* message);
};
lib_ext::lib_ext(void)
: last_error(0)
{
lib_init(& lib);
lib.on_error = (void (*)(struct lib*, char const*)) on_error;
}
void
lib_ext::do_something(void)
{
if (setjmp(jmpbuf))
{
throw std::runtime_error(last_error);
}
lib_do_something(& lib);
}
void
lib_ext::on_error(struct lib_ext* lib, char const* message)
{
// might be unsafe if 'message' is constructed at run-time
lib->last_error = message;
longjmp(lib->jmpbuf, -1);
}
That longjmp/throw looks pretty safe for me :)
Alex Shulgin
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]