Regarding the terminate handler,
As i understand it, when something bad happens in code, for example when we dont catch an exception,
terminate() is called, which in turn calls abort()
set_terminate(my_function) allows us to get terminate() to call a user specified function my_terminate.
my question is: where do these functions "live" they don't seem to be a part of the language, but work as if they are present in every single cpp file, without having to include any header file.
If there are default handler functions for terminate and abort that you did not install yourself, they'd have to be in the runtime library provided by your compiler.
Normally, every program is linked against the runtime library (e.g. glibc under Linux). Among other reasons, this is because the runtime library contains "hidden" code for essential things, e.g. code that calls your main function at startup.
I don't see why you think there is no need to include a header:
int main() {
abort();
}
gives the following error for me:
error: 'abort' was not declared in this scope
Neither C nor C++ have any "special" functions - if you want to use a function, you must declare it somehow. These two live in the C++ Standard Library, and are declared in cstdlib and exception. Of course, these headers themselves may be #included by other headers, thus making the functions available, but this is not specified by the standard.
set_terminate - terminate handler function
Sets f as the terminate handler function.
A terminate handler function is a function automatically called when the exception handling process has to be abandoned for some reason. This happens when a handler cannot be found for a thrown exception, or for some other exceptional circumstance that makes impossible to continue the handling process.
The terminate handler by default calls cstdlib's abort function
Related
I inherited a C++ project with a function defined like so:
void myDoc::parseDoc(string& path) throw(docError);
The parseDoc function calls a library that throws libError, and the main function that calls parseDoc catches both docError and libError and logs them. parseDoc doesn't throw any exceptions itself, but I would've expected the libErrors from the library to still get caught by main. They don't - I just get a core dump with nothing useful on the stack.
I tried various changes to parseDoc. Some of them get libError passed up the chain. and some don't:
catch libError and rethrow it - doesn't work
catch libError and copy it to a docError and throw that - works
specify throw(docError, libError) and not catch anything - works
remove the throw() from the function definition and not catch anything - works
So my question is - does adding a throw(docError) to this function definition specifically prevent other exceptions from being passed up the stack to the caller? If so, why would anyone want to do that? And if not specifying that a function throws exceptions just works the way I always thought exceptions were supposed to work, what's the point of the throw(e) specification in the first place?
Yes, a throw specification does not allow any exceptions except the specified to escape the function.
As for why anyone would want that, the idea is documentation, showing exactly which exceptions the function will throw.
However, in reality, the concept proved to be so useless that throw specifications were (or will be, not sure about the exact status) actually removed in a newer version of C++. So the correct action to take is number 4, removing the specification.
I'm building an error handling mechanism for a C++ application. Right now, I got the windows part done using VectoredExceptionHandling and I wanted to know if there is a similar concept on Solaris. Basically, whenever an exception is thrown from anywhere in the program, I want to have a callback called. Under windows, you can register a callback using AddVectoredExceptionHandler(). How do I do this for Solaris?
Not 100% if this will work, but you can try to mimic the way gdb's catchpoints work: see http://www.delorie.com/gnu/docs/gdb/gdb_31.html The key piece of info is this:
"To stop just before an exception handler is called, you need some knowledge of the implementation. In the case of GNU C++, exceptions are raised by calling a library function named __raise_exception which has the following ANSI C interface:
/* addr is where the exception identifier is stored.
id is the exception identifier. */
void __raise_exception (void **addr, void *id);
To make the debugger catch all exceptions before any stack unwinding takes place, set a breakpoint on __raise_exception"
So, my guess is that you could install your own __raise_exception via LD_PRELOAD trick, for example.
I am compiling my program with a 3rd party library. That library contains an error callback if an error occurs internally. Inside that error callback I am throwing an exception and I have a unit test to verify that when I do something invalid that the exception is thrown. This all works beautifully in Windows, but when I test this in linux (fedora) I am getting an abort from an uncaught exception.
I tried wrapping my call directly with a try-catch block but no luck. ( Also, all my code is running within the google test framework which also normally catches exceptions ). The only thing that seems to catch the exception is if I wrap the throw statement in a try block directly within the error callback.
Does anyone have any idea why this would happen and if there is a way to catch the exception?
When you interface with third-party libraries you usually have to catch all exception on the border between your code and their code:
int yourCallback( params )
{
try {
doStuff( params );
return Okay;
} catch (...) {
return Error;
}
}
The reason is you can't be sure that library is written in C++ or it uses the very same version of C++ runtime as your code uses.
Unless you're completely sure that code can deal with your exceptions you can't propagate exceptions to third-party code. The extreme example is COM where both your code and "other code" can be in whatever language and with whatever runtime and you are not allowed to let exceptions propagate through COM boundary.
Usually you should not throw exceptions "through" code you do not know anything about. It might be C code, which will not even clean up after itself.
How to deal with your concrete problem would require concrete information about the 3rd-party library you are interfacing with. What is that callback there for? To give you a chance to fix stuff? To inform you that an error occurred? Can you cancel whatever operation it is called from?
One way to deal with such a scenario is to store some information somewhere when the callback is called and check for that information when the actual processing finishes from your function that calls into that library.
I am using the Qt script engine in my application as an alternative way for the user to access its functionality. As such, I export some C++ classes to the Qt ScriptEngine, that will serve as the interface to the application. The problem is, these C++ classes can throw exceptions.
I have a "ScriptInterface" class running on its own thread, listening for requests to process scripts. So when I evaluate a user's script, I have a try/catch block around it to handle exceptions, and print the error to the console in the application.
...
try {
m_engine->evaluate(script, name);
}
catch (Exception const& e) {
// deal with it
}
catch (...) {
// scary message
}
This works perfectly in windows... but doesn't work in linux- the program terminates with this message:
terminate called after throwing an instance of 'Basilisk::InvalidArgumentException'
what(): N8Basilisk24InvalidArgumentExceptionE
Aborted
I had a hunch that it was because the exceptions bubbled up to the event handler (since the script engine uses signals to call the functions in my exported classes), so I reimplemented QApplication::notify, to handle exceptions there, but they weren't caught.
My question is, am I doing something fundamentally wrong? Also, as an alternative, is it possible to explicitly throw script exceptions from within my C++ classes?
Thanks in advance
EDIT: fixed the description to include the catch(...) statement.
UPDATE (SOLUTION): I "fixed" this problem by following a strategy similar to the one outlined in the accepted answer. Although I haven't gone to the source of why the exceptions don't get caught on linux (my suspicion now, is that m_engine->evaluate spawn a seperate thread on linux), but I have started using the intended way of exception throwing in Qt Scripts, and that is QScriptContext::throwError().
In cases where my function would look like this: (random example)
void SomeClass::doStuff(unsigned int argument) {
if (argument != 42) {
throw InvalidArgumentException(
"Not the answer to Life, the Universe and Everything.");
}
// function that is not part of the scripting environment,
// and can throw a C++ exception
dangerousFunction(argument);
}
It is now this: (pay particular attention to the return type)
QScriptValue SomeClass::doStuff(unsigned int argument) {
if (argument != 42) {
// assuming m_engine points to an instance of
// QScriptEngine that will be calling this function
return m_engine->currentContext()->throwError(QScriptContext::SyntaxError,
"Not the answer to Life, the Universe and Everything.");
}
try {
// function that is not part of the scripting environment,
// and can throw a C++ exception
dangerousFunction(argument);
} catch (ExpectedException const& e) {
return m_engine->currentContext()->throwError(QScriptContext::UnknownError,
e.message());
}
// if no errors returned, return an invalid QScriptValue,
// equivalent to void
return QScriptValue();
}
So where does one deal with these script errors? After the call to QScriptEngine::evaluate() you can check whether there are any uncaught exceptions, with QScriptEngine::hasUncaughtException(), obtain the error object with uncaughtException(), and now you have the message, the trace, and line number in the script where the error occured!
Hope this helps someone out!
I ran into a similar type of problem when trying to use SWIG with Python to wrap C++ libraries. Eventually what happened was that I made a stub for all the wrapped classes which caught the exception and failed quietly. Luckily I had the luxury of wrapping functionality which only passed container classes and state pattern objects, so I could easily check if something was amiss. May I suggest the same for you?
Wrap the functions you want with another function, same interface except the return value.
Create an object that contains not only the requested return type but also an error indicator.
Have the script make sure to check for the exceptions.
And yes, it's very possible for a script engine to throw C++ exceptions if you've given it access to an exception factory (a class whose sole purpose is to throw C++ exceptions.)
Run your program under a debugger and place a breakpoint inside your runtime library's terminate() function. That way you'll stop on terminate() in the debugger and by inspecting the call stack you will then see from where terminate() was called.
Whilst compiling with avr-gcc I have encountered linker errors such as the following:
undefined reference to `__cxa_pure_virtual'
I've found this document which states:
The __cxa_pure_virtual function is an error handler that is invoked when a pure virtual function is called.
If you are writing a C++ application that has pure virtual functions you must supply your own __cxa_pure_virtual error handler function. For example:
extern "C" void __cxa_pure_virtual() { while (1); }
Defining this function as suggested fixes the errors but I'd like to know:
what the purpose of this function is,
why I should need to define it myself and
why it is acceptable to code it as an infinite loop?
If anywhere in the runtime of your program an object is created with a virtual function pointer not filled in, and when the corresponding function is called, you will be calling a 'pure virtual function'.
The handler you describe should be defined in the default libraries that come with your development environment. If you happen to omit the default libraries, you will find this handler undefined: the linker sees a declaration, but no definition. That's when you need to provide your own version.
The infinite loop is acceptable because it's a 'loud' error: users of your software will immediately notice it. Any other 'loud' implementation is acceptable, too.
1) What's the purpose of the function __cxa_pure_virtual()?
Pure virtual functions can get called during object construction/destruction. If that happens, __cxa_pure_virtual() gets called to report the error. See Where do "pure virtual function call" crashes come from?
2) Why might you need to define it yourself?
Normally this function is provided by libstdc++ (e.g. on Linux), but avr-gcc and the Arduino toolchain don't provide a libstdc++.
The Arduino IDE manages to avoid the linker error when building some programs because it compiles with the options "-ffunction-sections -fdata-sections" and links with "-Wl,--gc-sections", which drops some references to unused symbols.
3) Why is it acceptable to code __cxa_pure_virtual() as an infinite loop?
Well, this is at least safe; it does something predictable. It would be more useful to abort the program and report the error. An infinite loop would be awkward to debug, though, unless you have a debugger that can interrupt execution and give a stack backtrace.