Passing exceptions across a C API boundary - c++

I am writing a library in C++ which uses an older C API. The client of my library can specify callback functions, which are indirectly called through my library which is called through the C API. This means that all exceptions in the client callbacks must be handled.
My question is this: how can I catch the exception on one side of the boundary and re-throw it once the C API boundary has been recrossed and the execution is back in C++ land so that the exception can be handled by client code?

With C++11 we could use:
std::exception_ptr active_exception;
try
{
// call code which may throw exceptions
}
catch (...)
{
// an exception is thrown. save it for future re-throwing.
active_exception = std::current_exception();
}
// call C code
...
// back to C++, re-throw the exception if needed.
if (active_exception)
std::rethrow_exception(active_exception);
Before C++11 these can still be used via Boost Exception.

Some environments support this more or less directly.
For instance, if you enable structured exception handling and C++ exceptions through the /EH compiler switch, you can have C++ exceptions implemented over Microsoft's structured exception handling ("exceptions" for C). Provided these options are set when compiling all your code (the C++ at each end and the C in the middle) stack unwinding will "work".
However, this is almost always a Bad Idea (TM). Why, you ask? Consider that the piece of C code in the middle is:
WaitForSingleObject(mutex, ...);
invoke_cxx_callback(...);
ReleaseMutex(mutex);
And that the invoke_cxx_callback() (....drum roll...) invokes your C++ code that throws an exception. You will leak a mutex lock. Ouch.
You see, the thing is that most C code is not written to handle C++-style stack unwinding at any moment in a function's execution. Moreover, it lacks destructors, so it doesn't have RAII to protect itself from exceptions.
Kenny TM has a solution for C++11 and Boost-based projects. xxbbcc has a more general, albeit more tedious solution for the general case.

You can probably pass a structure across the C interface that gets filled out with error information in case of an exception and then when that is received on the client side, check it and throw an exception inside the client, based on data from the structure. If you only need minimal information to recreate your exception, you can probably just use a 32-bit/64-bit integer as an error code. For example:
typedef int ErrorCode;
...
void CMyCaller::CallsClient ()
{
CheckResult ( CFunction ( ... ) );
}
void CheckResult ( ErrorCode nResult )
{
// If you have more information (for example in a structure) then you can
// use that to decide what kind of exception to throw.)
if ( nResult < 0 )
throw ( nResult );
}
...
// Client component's C interface
ErrorCode CFunction ( ... )
{
ErrorCode nResult = 0;
try
{
...
}
catch ( CSomeException oX )
{
nResult = -100;
}
catch ( ... )
{
nResult = -1;
}
return ( nResult );
}
If you need more information than a single int32/int64 then you can allocate a structure before the call and pass its address to the C function which will, in turn, catch exceptions internally and if they happen, throws an exception on its own side.

Related

Properly terminating program. Using exceptions

Question:
Is using exceptions the proper way to terminate my program if all I want is to display an error message and close (accounting that I may be deep in the program)? Or can I just explicitly call something like exit(EXIT_FAILURE) instead?
What I'm Currently Doing:
I'm working on a game project and am trying to figure out the best way to terminate the program in the case of an error that calls for such an action. For example, in the case the textures can't be loaded I display an error message and terminate the program.
I'm currently doing this with exceptions like so:
int main()
{
Game game;
try
{
game.run();
}
catch (BadResolutionException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Resolution");
return 1;
}
catch (BadAssetException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Assets");
return 1;
}
catch (std::bad_alloc & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Memory");
return 1;
}
return 0;
}
All but bad_alloc are my own defined exceptions derived from runtime_error.
I don't need any manual resource cleanup and I'm using std::unique_ptr for any dynamic allocation. I just need to display the error message and close the program.
Research/Alternatives to Exceptions:
I've looked up a lot of posts on SO and other places and have seen others say anything from don't use exceptions, to use exceptions but your using them wrong. I've also looked up explicitly calling something like exit().
Using exit() sounds nice but I read it won't go back through the call stack up to main cleaning everything up (if I can find this again I'll post the link). Additionally, according to http://www.cplusplus.com/reference/cstdlib/exit/ this should not be used if multiple threads are active. I do expect to be creating a second thread for a short time at least once, and an error could occur in that thread.
Not using exceptions was mentioned in some replies here in relation to games https://gamedev.stackexchange.com/questions/103285/how-industy-games-handle-their-code-errors-and-exceptions
Use exceptions was discussed here: http://www.quora.com/Why-do-some-people-recommend-not-using-exception-handling-in-C++
There are a number of other sources I've read but those were the most recent I looked at.
Personal Conclusion:
Due to my limited experience of working with error handling and using exceptions, I'm not sure if I'm on the right track. I've chosen the route of using exceptions based on the code I posted above. If you agree that I should tackle those cases with exceptions, am I using it correctly?
It's generally considered good practice to let all exceptions propagate through to main. This is primarily because you can be sure the stack is properly unwound and all destructors are called (see this answer). I also think it's more organised to do things this way; you always known where your program will terminate (unless the program crashes). It's also facilitates more consistent error reporting (a point often neglected in exception handling; if you can't handle the exception, you should make sure your user knows exactly why). If you always start with this basic layout
int main(int argc, const char **argv)
{
try {
// do stuff
return EXIT_SUCCESS;
} catch (...) {
std::cerr << "Error: unknown exception" << std::endl;
return EXIT_FAILURE;
}
}
then you won't go far wrong. You can (and should) add specific catch statements for better error reporting.
Exceptions when multithreading
There are two basic ways of executing code asynchronously in C++11 using standard library features: std::async and std::thread.
First the simple one. std::async will return a std::future which will capture and store any uncaught exceptions thrown in the given function. Calling std::future::get on the future will cause any exceptions to propagate into the calling thread.
auto fut = std::async(std::launch::async, [] () { throw std::runtime_error {"oh dear"}; });
fut.get(); // fine, throws exception
On the other hand, if an exception in a std::thread object is uncaught then std::terminate will be called:
try {
std::thread t {[] () { throw std::runtime_error {"oh dear"};}};
t.join();
} catch(...) {
// only get here if std::thread constructor throws
}
One solution to this could be to pass a std::exception_ptr into the std::thread object which it can pass the exception to:
void foo(std::exception_ptr& eptr)
{
try {
throw std::runtime_error {"oh dear"};
} catch (...) {
eptr = std::current_exception();
}
}
void bar()
{
std::exception_ptr eptr {};
std::thread t {foo, std::ref(eptr)};
try {
// do stuff
} catch(...) {
t.join(); // t may also have thrown
throw;
}
t.join();
if (eptr) {
std::rethrow_exception(eptr);
}
}
Although a better way is to use std::package_task:
void foo()
{
throw std::runtime_error {"oh dear"};
}
void bar()
{
std::packaged_task<void()> task {foo};
auto fut = task.get_future();
std::thread t {std::move(task)};
t.join();
auto result = fut.get(); // throws here
}
But unless you have good reason to use std::thread, prefer std::async.
There's nothing wrong with catching unrecoverable errors and shutting down your program this way. In fact, it's how exceptions should be used. However, be careful not to cross the line of using exceptions to control the flow of your program in ordinary circumstances. They should always represent an error which cannot be gracefully handled at the level the error occurred.
Calling exit() would not unwind the stack from wherever you called it. If you want to exit cleanly, what you're already doing is ideal.
You have already accepted an answer, but I wanted to add something about this:
Can I just explicitly call something like exit() instead?
You can call exit, but (probably) shouldn't.
std::exit should be reserved for situations where you want to express "exit right now!", not simply "application has nothing left to do".
As an example, if you were to write a controller for a laser used in cancer treatments, your first priority in case something went wrong would be to shut down the laser and call std::exit - or possibly std::terminate (to ensure any side effects of a hanging, slow or crashing application do not kill a patient).
Similar to how exceptions should not be used for controlling application flow, exit should not be used to stop the application in normal conditions.
Is using exceptions the proper way to terminate my program if all I want is to display an error message and close (accounting that I may be deep in the program)?
Yes. This is the reason for using exceptions. An error occurred deep down in the code and something at a higher level will handle it. In your case, at the highest level.
There are arguments for/against exceptions vs. error codes, and this is a good read:
Exceptions or error codes
Can I just explicitly call something like exit() instead?
You can, but you may end up duplicating your logging code. Also, if in the future you decide that you want to handle an exception differently you will have to change all your exit calls. Imagine you wanted a different message, or to fall back on an alternative process.
Another similar question:
Correct usage of exit() in c++?
You also have a flaw in your approach as you don't handle all (C++) exceptions. You want something like this:
int main()
{
Game game;
try
{
game.run();
}
catch (BadResolutionException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Resolution");
return 1;
}
catch (BadAssetException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Assets");
return 1;
}
catch (std::bad_alloc & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Memory");
return 1;
}
catch (...)
{
// overload?
Notification::showErrorMessage("ERROR: Unhandled");
return 1;
}
return 0;
}
If you don't handle all* exceptions you could have the game terminate without telling you anything useful.
You can't handle ALL exceptions. See this link:
C++ catching all exceptions
From the documentation:
[[noreturn]] void exit (int status);
Terminate calling process
Terminates the process normally, performing the regular cleanup for terminating programs.
Normal program termination performs the following (in the same order):
Objects associated with the current thread with thread storage duration are destroyed (C++11 only).
Objects with static storage duration are destroyed (C++) and functions registered with atexit are called.
All C streams (open with functions in ) are closed (and flushed, if buffered), and all files created with tmpfile are removed.
Control is returned to the host environment.
Note that objects with automatic storage are not destroyed by calling exit (C++).
If status is zero or EXIT_SUCCESS, a successful termination status is returned to the host environment.
If status is EXIT_FAILURE, an unsuccessful termination status is returned to the host environment.
Otherwise, the status returned depends on the system and library implementation.
For a similar function that does not perform the cleanup described above, see quick_exit.

C++ potentially-throwing code at COM method boundaries

C++ exceptions can't cross COM module boundaries.
So, assume we are in a COM method body, and some C++ potentially-throwing method/function is called (this can throw because e.g. STL classes are used):
STDMETHODIMP CSomeComServer::DoSomething()
{
CppDoSomething(); // <--- This may throw C++ exceptions
return S_OK;
}
Q1. Is the above code a viable implementation?
For example, if that code is part of a context menu shell extension, if the C++ CppDoSomething() function throws a C++ exception, what does Explorer do? Does it catch the C++ exception and unload the shell extension? Does it just crash Explorer (making it possible to analyze the problem using a crash dump) following a fail-fast approach?
Q2. Would an implementation like this be better?
STDMETHODIMP CSomeComServer::DoSomething()
{
//
// Wrap the potentially-throwing C++ code call in a safe try/catch block.
// C++ exceptions are caught and transformed to HRESULTs.
//
try
{
CppDoSomething(); // <--- This may throw C++ exceptions
return S_OK;
}
//
// Map C++ std::bad_alloc exception to E_OUTOFMEMORY HRESULT.
//
catch(const std::bad_alloc& ex)
{
// ... Log the exception what() message somewhere,
// e.g. using OutputDebugString().
....
return E_OUTOFMEMORY;
}
//
// Map C++ std::exception exception to generic E_FAIL.
//
catch(const std::exception& ex)
{
// ... Log the exception what() message somewhere,
// e.g. using OutputDebugString().
....
return E_FAIL;
}
}
Q3. Or would it be even better, if a C++ exception is thrown, to just set an internal flag (e.g. a bool m_invalid data member) to put the COM server in a state such that it can't work anymore, so every successive call to its method returns some error code, like E_FAIL or some other specific error?
Q4. Finally, assuming that Q2/Q3 are good implementation guidelines, it's possible to hide the verbose try/catch guard in some convenient preprocessor macros (that can be reused in every COM method body), e.g.
#define COM_EXCEPTION_GUARD_BEGIN try \
{
#define COM_EXCEPTION_GUARD_END return S_OK; \
} \
catch(const std::bad_alloc& ex) \
{ \
.... \
return E_OUTOFMEMORY; \
} \
catch(const std::exception& ex) \
{ \
.... \
return E_FAIL; \
}
//
// May also add other mappings, like std::invalid_argument --> E_INVALIDARG ...
//
STDMETHODIMP CSomeComServer::DoSomething()
{
COM_EXCEPTION_GUARD_BEGIN
CppDoSomething(); // <--- This may throw C++ exceptions
COM_EXCEPTION_GUARD_END
}
STDMETHODIMP CSomeComServer::DoSomethingElse()
{
COM_EXCEPTION_GUARD_BEGIN
CppDoSomethingElse(); // <--- This may throw C++ exceptions
COM_EXCEPTION_GUARD_END
}
Using modern C++11/14, is it possible to replace the aforementioned preprocessor macros with something else, more convenient, more elegant, just better?
Never let exceptions propagate across COM boundary, otherwise the behavior is undefined and may include your C++ runtime terminate() being called, the process going nuts and other nice bonuses. Just don't do it. Even if you "tested" it in some configuration - it's still undefined behavior and will silently break should minor environment or implementation changes occur.
You should catch and translate all C++ exceptions into HRESULTs and optionally set IErrorInfo with details. You can do so with macros wrapping each COM server method implementation or by copy-pasting this code everywhere - guess which is more maintainable.
The idea with driving the server into "invalid" state may make sense in some extreme situations but I can't imagine them at the moment. I guess it's not a universal solution. In general cases if you have exception safe code you shouldn't need this at all.

Why doesn't my program catch an exception from dereferencing a null pointer?

Can some please explain why this exception isn't caught.
try {
// This will cause an exception
char *p = 0;
char x = 0;
*p = x;
}
catch (...) {
int a = 0;
}
When I run the program it dies on the line *p = x. I would expect that the catch block would cause this exception to be ignored.
I'm using the Qt Creator (2.2) with Qt 4.7.2 compiling with Visual Studios 2008 on Windows 7 32 bit.
There is no C++ exception being thrown here. You are causing undefined behavior because *p = x derefences a pointer with a null pointer value.
An exception is only propogated when you, or code you call, executes a throw expression. Undefined behaviour is not usually catchable.
Structured exception handling __try and __catch will catch system faults, see:
http://msdn.microsoft.com/en-us/library/swezty51(v=vs.80).aspx
Dereferencing a NULL pointer is undefined behaviour. In general, this will trigger a processor trap, and an OS level error. This may then be mapped to a signal, such as SIGSEGV, or to an Access Violation error, or it may abort your program, or do anything else.
On Windows, it is mapped to a "structured exception", which is a different beast to a C++ exception. Depending on how you've got MSVC configured, you may be able to catch this with catch(...), but not always.
If you want that you need to write a pointer test:
template<typename T>
inline T* ptr_test(T* test)
{
if (test == NULL)
{ throw std::runtime_error("Null Exceception");
}
return test;
}
Then your code looks like this:
try
{
// This will cause an exception
char* p = 0;
char x = 0;
*ptr_test(p) = x; // This is what java does.
// Fortunately C++ assumes you are smart enough to use pointers correctly.
// Thus I do not need to pay for this test.
//
// But if you want to pay for the test please feel free.
}
catch (...)
{
int a = 0;
}
You need to use the /EHa compiler option to switch on the (Microsoft compiler specific) feature which will enable SEH (Structured Exception Handling) exceptions (which is what your null access triggers) to be catchable by catch(...).
Having said that, I wouldn't recommend using /EHa. Better to use the __try/__except extension or the SEH API directly and keep your handling of "structured" exceptions separate from handling of C++ exceptions. Why ? Because C++ exceptions are just another perfectly legitimate well defined control flow mechanism, but most things which trigger SEH exceptions are likely to indicate your software has entered the realm of undefined behaviour and really the only sensible thing to do is exit gracefully. Using /EHa leads to this vital difference becoming unnecessarily blurred.
It's not caught because its not an exception - nothing is throwing. You're accessing null/unallocated memory which causes a segmentation fault which is a signal from the operating system itself.
Signals can only be caught by signal handlers, exceptions will not help you with those.
Exceptions only really help in areas where something might call throw(), like a library throwing an exception when you cause a divide-by-zero with the parameters you provided it.
All you're doing right now is dereferencing a null pointer, it is not an exception.
If you want this code to catch something, you have to throw something first. Say, something like:
try {
// This will cause an exception
char *p = 0;
char x = 0;
if (p == 0) throw 1;
*p = x;
}
catch (...) {
int a = 0;
}
Obviously, the catch block in the above example will always be executed.

Stack unwinding in C++ when using Lua

I recently stumbled into this this C++/Lua error
int function_for_lua( lua_State* L )
{
std::string s("Trouble coming!");
/* ... */
return luaL_error(L,"something went wrong");
}
The error is that luaL_error use longjmp, so the stack is never unwound and s is never destructed, leaking memory. There are a few more Lua API's that fail to unwind the stack.
One obvious solution is to compile Lua in C++ mode with exceptions. I, however, cannot as Luabind needs the standard C ABI.
My current thought is to write my own functions that mimic the troublesome parts of the Lua API:
// just a heads up this is valid c++. It's called a function try/catch.
int function_for_lua( lua_State* L )
try
{
/* code that may throw Lua_error */
}
catch( Lua_error& e )
{
luaL_error(L,e.what());
}
So my question: Is function_for_lua's stack properly unwound. Can something go wrong?
If I understand correctly, with Luabind functions that throw exceptions are properly caught and translated anyway. (See reference.)
So whenever you need to indicate an error, just throw a standard exception:
void function_for_lua( lua_State* L )
{
std::string s("Trouble coming!");
/* ... */
// translated into lua error
throw std::runtime_error("something went wrong");
}
Disclaimer: I've never used Lubind.

What happens if I use "throw;" without an exception to throw?

Here's the setup.
I have a C++ program which calls several functions, all of which potentially throw the same exception set, and I want the same behaviour for the exceptions in each function
(e.g. print error message & reset all the data to the default for exceptionA; simply print for exceptionB; shut-down cleanly for all other exceptions).
It seems like I should be able to set the catch behaviour to call a private function which simply rethrows the error, and performs the catches, like so:
void aFunction()
{
try{ /* do some stuff that might throw */ }
catch(...){handle();}
}
void bFunction()
{
try{ /* do some stuff that might throw */ }
catch(...){handle();}
}
void handle()
{
try{throw;}
catch(anException)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
catch(anotherException)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
catch(...)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
}
Now, what happens if "handle" is called outside of the exception class.
I'm aware that this should never happen, but I'm wondering if the behaviour is undefined by the C++ standard.
If handle() is called outside the context of an exception, you will throw without an exception being handled. In this case, the standard (see section 15.5.1) specifies that
If no exception is presently being handled, executing a throw-expression with no operand calls terminate().
so your application will terminate. That's probably not what you want here.
If you use throw inside of a catch block, it will rethrow the exception. If you use throw outside of a catch block, it will terminate the application.
Never, never, never use catch(...) as you might catch application errors that you don't want to catch, e.g. bugs, access violations (depending on how you compiled).
Read the great John Robbins book (Debugging Windows Applications) in which he explains more in detail why you shouldn't do it.