C++ custom exceptions: run time performance and passing exceptions from C++ to C
- by skyeagle
I am writing a custom C++ exception class (so I can pass exceptions occuring in C++ to another language via a C API).
My initial plan of attack was to proceed as follows:
//C++
myClass
{
public:
myClass();
~myClass();
void foo() // throws myException
int foo(const int i, const bool b) // throws myException
} * myClassPtr;
// C API
#ifdef __cplusplus
extern "C" {
#endif
myClassPtr MyClass_New();
void MyClass_Destroy(myClassPtr p);
void MyClass_Foo(myClassPtr p);
int MyClass_FooBar(myClassPtr p, int i, bool b);
#ifdef __cplusplus
};
#endif
I need a way to be able to pass exceptions thrown in the C++ code to the C side. The information I want to pass to the C side is the following:
(a). What
(b). Where
(c). Simple Stack Trace (just the sequence of error messages in order they occured, no debugging info etc)
I want to modify my C API, so that the API functions take a pointer to a struct ExceptionInfo, which will contain any exception info (if an exception occured) before consuming the results of the invocation.
This raises two questions:
Question 1
1. Implementation of each of the C++ methods exposed in the C API needs to be enclosed in a try/catch statement. The performance implications for this seem quite serious (according to this article):
"It is a mistake (with high runtime
cost) to use C++ exception handling
for events that occur frequently, or
for events that are handled near the
point of detection."
At the same time, I remember reading somewhere in my C++ days, that all though exception handling is expensive, it only becmes expensive when an exception actually occurs. So, which is correct?. what to do?. Is there an alternative way that I can trap errors safely and pass the resulting error info to the C API?. Or is this a minor consideration (the article after all, is quite old, and hardware have improved a bit since then).
Question 2
I wuld like to modify the exception class given in that article, so that it contains a simple stack trace, and I need some help doing that. Again, in order to make the exception class 'lightweight', I think its a good idea not to include any STL classes, like string or vector (good idea/bad idea?).
Which potentially leaves me with a fixed length C string (char*) which will be stack allocated. So I can maybe just keep appending messages (delimted by a unique separator [up to maximum length of buffer])...
Its been a while since I did any serious C++ coding, and I will be grateful for the help.
BTW, this is what I have come up with so far (I am intentionally, not deriving from std::exception because of the performance reasons mentioned in the article, and I am instead, throwing an integral exception (based on an exception enumeration):
class fast_exception
{
public:
fast_exception(int what, char const* file=0, int line=0)
: what_(what), line_(line), file_(file)
{/*empty*/}
int what() const { return what_; }
int line() const { return line_; }
char const* file() const { return file_; }
private:
int what_;
int line_;
char const[MAX_BUFFER_SIZE] file_;
}