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.
Related
I have watched Mike Acton's talk on Data-Oriented Design and C++.
As he stated at 8min30sec that they don't use exceptions, they cannot force it to be off on third party libraries. Therefore they "sandbox around" these libraries.
My questions are:
1.
What is exactly meant by "sandboxing around" libraries using exceptions, when my codebase runs with disabled exceptions and how does it work and how do I do that? (are there differences on platforms (Win/Linux/Mac, consoles or mobile?)
2. When using the standard library (which uses exceptions, as in new and the alikes) how I "sandbox" them - or is it the same principle as in 1.?
You can sandbox the exception by just caching it in a wrapper. Let's suppose you have:
a third party library T that DOES use exceptions
your application A that DOES NOT use exceptions.
You then create a wrapper W (compiled WITH exceptions enabled) that will wrap T but catch all exceptions wherever it exists and, for example, replace by and error code, like this:
// this one comes from the original library T that throws exceptions
void someFunctionInT();
// this will be your wrapper around the function above
int someFunctionInW()
{
try
{
someFunctionInT();
}
catch (...)
{
return -1;
}
return 0;
}
So, this way, your wrapper W should NOT throw any exception and you can use safely link against your application A.
Obviously, this is just a simple example. But you can do something a little "fancier" once at this time you already "paid" for the exception handling. For example, you can test the exception and return different error codes or prepare an error message to be retrieved from another function, etc, etc... up to your creativity. :-)
I would like to handle of all the C++ exceptions with C++ Builder to generate a crash report that could help me to debug applications when they are installed and used at the clients' places.
I tried to use the function SetUnhandledExceptionFilter but it does not work cause the VCL intercepts the exceptions and does not throw them again.
So I tried this, it doesn't work as well:
unsigned int Filter( unsigned int uiExCode, EXCEPTION_POINTERS *pt )
{
// might create the crash dump....
MessageBox( NULL, L"ENFIN", L"", 0 );
return EXCEPTION_CONTINUE_SEARCH;
}
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
try
{
Application->Initialize();
Application->MainFormOnTaskBar = true;
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
__except( Filter( GetExceptionCode(), GetExceptionInformation() ) )
{
// Some code to clear
}
return 0;
}
I don't want to use external libs such as EurekaLog or MadExcept.
Is anyone has an idea how to prevent the VCL from catching all of the exception ?
Thanks.
In my opinion, an automated mapping between VCL and STL is a very big deal.
The solution described in Translate C++ Exceptions to VCL Exceptions causes two hierarchies of logic to be managed, so you will have to catch both EOutOfRange and CppStdOutOfRange if you don't know if the called implementation is VCL or STL... And it's also error prone as the frameworks may evolve.
My advice is to catch every "expectable" "foreign" exception very early and translate it into the appropriate exception of the the one exception hierarchy of your choice: Make sure that all exception classes (that will actually "fly" through your application) inherit (mostly indirectly) from one base class.
One important point that you may have forgotten is, as Hans Passant mentioned, to catch not only the application setup exception (as you currently do), but also the runtime exceptions (i.e. all exceptions thrown within the call of the method TApplication::Run). This can only be done by assigning the event Application->OnException - re-read the docs concerning how to do that technically.
My warm suggestion for a reasonable global exception handler is to show and log a message, then terminate the application. Or even better in this order:
log the message
store it to a global buffer
leave Run by calling Application->Terminate
display the message box in main
a modal message box will keep your poisoned program running - and you don't really know what it does.
As far as I know, there's no straightforward way to achieve what you want. Here's an interesting article that provides information on the subject and explores some possible solutions: http://www.audacia-software.de/en/bcb/external-exception-eefface.htm
In our application (c++) we load 3rd party DLLs using LoadLibrary.
Sometimes these DLLs cause exceptions, such as "Access violation reading location 0x00000000..".
Is it possible to recover from such an exception, for example using try & catch or some other mechanism? in other world, is that possible to create a sandbox within the same process that withstand such events?
Thank you
No. It's not. A DLL has unrestricted access to the process context that calls it. You need to run untrustable DLLs in their own process context.
In Windows, with VisualStudio compiler, may use SEH mechanism.
__try
{
char* ptr = 0;
char val = *ptr;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
{
std::cout<<"AV"<<std::endl;
}
Use option /EHa.
You could try a different type of exception handler:
__try
{
// Code that might cause an access violation goes here.
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
int code = _exception_code();
}
Beware though, such handlers can't be used in any routine where C++ objects need stack unwinding as the compiler will warn you (irritatingly).
You can try the /EH flag - http://msdn.microsoft.com/en-us/library/1deeycx5%28v=vs.80%29.aspx - in Visual Studio, but access violation exceptions most likely mean you're doing something very wrong. I'd let the program crash and try to solve the exception, rather than catching it.
It is not possible in c++ if, it is not possible throws a crossmodules exceptions anymore in any case you will have a memory corruption in your application so you have to find out what is going wrong in your dll. You can check the reason you cant throw exception from dll here:
http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL
The people behind Runtime-Compiled C++ are using a thing called Structured Exception Handling for their DLL crash-handling routines. Dig into their website or ask them if you want some code samples.
According to the MSDN, the /EHa switch enables "C++ exception handling with structured exception handling exceptions". So if you're using the msvc compiler, you might want to try this.
Is there a way of temporally disable first-chance exceptions in Visual C++?
Something like this:
void someFunc() {
disableFirstChanceExceptions();
try {
// some code
}
catch (std::exception& e) {
// some code
}
catch (...) {
// some code
}
enableFirstChanceExceptions();
}
I know what first-chance-exceptions are and how to use them.
The problem is, that I am distributing a DLL, in which exceptions are used.
Unfortunately if a customer is using a debugger with his program, he will notice my intern exceptions.
It is not that I want to hide them, it is more that I want to get rid of these support questions.
Your code throws exceptions.
Your customers insist on running debuggers against your code, and explicitly configure it to break on first-chance exceptions.
You have basically two options:
don't throw exceptions, or
ignore when your customer is being stupid. What your code does internally is none of their business as long as it works as intended.
I'd suggest the latter. If they have a problem with exceptions being thrown and caught inside third-party code, they'll find themselves unable to use a lot of libraries. They'll need to grow up and start acting like they know what they're doing.
First chance exceptions are not something that can be turned on and off in your code (speaking only about windows, vs, c++ chain, not familiar with other platforms). This is construct is built into the run time system to make debugging possible. The debugger can be configured to ignore some or all first chance exceptions. You can use ctrl + alt + e to bring up the VS debugger's exception handling behavior menu. This will allow clients debugging to filter what the want caught by the debugger.
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.