I'm pretty good with exception handling in C/C++ - I know all about creating custom classes from std::exception, when to throw, when to fall back on simpler things like UNIX errno, etc. I do have one thing I'm always a little foggy about though when it comes to accessing COTS code.
If I call a function from a COTS library like so:
void DoSomething()
{
try
{
CallCotsFunction();
}
catch (CotsException& ce)
{
//Cots error caught
}
catch (...)
{
//Unknown e开发者_JAVA技巧rror caught.
}
}
If CallCotsFunction()
has poor exception handling or no exception handling and performs a divide-by-zero or something, will it get propagated up to my exception handlers?
If CallCotsFunction()
causes a sig-11 or something of that sort will it get caught, or are all bets off with something that severe?
On Linux, unix signals do not normally trigger exception handlers. Additionally, it is, generally speaking, unsafe to throw an exception from a signal handler (at a minimum, you must compile with -fnon-call-exceptions
; even then I've seen mixed reports).
Note also that you should always catch exceptions by reference, to avoid slicing:
catch (CotsException &ce)
{
// ...
}
In short: If your third-party library lets a C++ exception propagate up without being caught, yes, it'll hit your application. If it's derived from std::exception or some other common type, you should be able to catch it. If it's some internal type not exposed to you, you won't be able to catch it by name (but catch (...)
should catch it). CPU exceptions (divide by zero, segfaults, etc) will not automatically trigger C++ exceptions, unless you or the library installs a signal handler to convert it; in which case the code triggering the signal MUST be built with -fnon-call-exceptions
for stack unwind to work properly.
In general, if the library triggers a fault such as SIGFPU or SIGSEGV, the results of trying to recover with an exception are unpredictable; the library may not be expecting to unwind its stack at that point, and with SIGSEGV, you may have heap corruption that causes the exception-throwing system itself to fault. I would not recommend trying to recover in this way - just let the process die.
Signals are independent of, and predate, C++ exceptions.
A divide-by-zero can be caught either by your library, in which case the library can throw a real C++ exception, or it will be caught by your CPU causing a signal to terminate your process.
I would not suggest throwing a C++ exception from inside a signal handler.
Any exception not caught by the function will propagate up to the caller. Whether the caller should bother catching such an exception is another matter and depends on whether the caller can reasonably do anything about it. For example, if the function divides by zero and an exception occurs from that, what state was everything else in? If you don't know, then is it really wise to allow the program to continue running at all?
I would treat signal-handling the same way. If you haven't been told to expect the third-party library to trigger signals, then you shouldn't try to handle them.
精彩评论