Throwing C++ Exceptions Across Dll Boundaries

Is this trick to throw exceptions across DLL boundaries a bad idea?

This may work, but only if the throwing mechanism and stack unrolling code of the two code bases is basically identical and compatible.

In order to destroy each of the objects it should after that throw, the client code has to be able to understand how the DLL code sets up its stack and where it registers destructors to be cleaned up, etc. It may be the case that your client and DLL code compilers are sufficiently in agreement for this to work, if you are lucky.

Which sort of ruins the point of your design.


An approach that might work is to carefully marshal the exceptions over the DLL boundary.

The "C" API for your DLL returns information about what exceptions (if any) where thrown. A C++ header-file only wrapper that the client compiles calls the "C" API, and in client-compiled code detects the exception, unwraps it, and throws it.

Inside the DLL, the "C" API does a try{}catch(){}, and calls the internal C++ library. The catch clause populates the exception information into the "C" API return value, and returns.

Now internal exceptions are thrown, caught within the C++ DLL, marshaled over the DLL-boundary in a "C" API, packaged back into exceptions on the client-code side, and rethrown.

Throwing exception from constructor across DLL boundary

I think your approach is the right one. Let's export factories for objects instead of objects itself.

Btw it could be projected so that for each of your DLLs you could have an export function with the same name. So that within that export function you could have if-else block that enumerates through all the factories of the DLL and tries to construct the requested object. (Let's say, the objects are identified by name, crc32 of name, hash of name etc)

I think it could be several approaches here.
For example, instead of the common exported function you could register each of the DLL's factories on the common object on DLLMain/Attach event or handle a custom DLLMain event - your own - so that you could put the Neo object address as a param to DLLMain and register the exact factory on it for each DLL.

But the common thing is to use factories when your object could throw an expection on ctor/init method.

C++ Windows DLL: Exception Handling in Different Function

Exceptions are not allowed to pass over the DLL boundary into the calling executable. The caller is not guaranteed to know how to handle an exception properly, especially in regards to cleanup, even if the executable and DLL are compiled with the same compiler. Or, the caller may not even understand what an exception is at all, if the executable and DLL are compiled in different languages.

If you need to convey error information to the caller, you must do so using a return value, an output parameter, a separate function call, etc. Things that are more-or-less universally supported across compilers/languages.

DO NOT throw exceptions over the DLL boundary into the caller!

UPDATE

You are already catching std::exception& in GetNumbers() (though, it really should be const std::exception & instead), so simply have CheckException() actually throw a std::exception object, don't try to return it, eg:

template<typename T>
void CheckException (const T *var, int status, const string &mesg)
{
if (var == NULL || status == ERROR) {
// or make a custom class derived from std::exception, if you want...
throw std::runtime_error(mesg);
}
}

...

try
{
const char* name = input->getName(&status, &mesg);
CheckException(name, status, mesg);

const char* age = input->getAge(&status, &mesg);
CheckException(age, status, mesg);

// Many other similar calls to client...

vector<int> *myVectorNumers = input->getNumberArray(&status, &mesg);
CheckException(myVectorNumers, status, mesg);

vector<int> *myVectorInfos = input->getInfoArray(&status, &mesg);
CheckException(myVectorInfos, status, mesg);

// Many other similar calls to client...
}
catch (const std::exception e&)
{
// TODO
}

Why is this exception not being caught across DLLs?

I have finally figured out what the problem is, and in this particular case, it is nothing to do with throwing exceptions between DLLs.

The problem is occurring due to an exception handler hook being installed further up the call stack. I diagnosed this by adding try, catch(...) blocks to every level in the library until I found the point at which the exception wasn't propagated. When I commented out the exception handler hook registration code, the exception was successfully propagated.

I now have to figure out the workings of exception handler hooks, which is outside the scope of this question. Thanks to everyone who shared their answers.



Related Topics



Leave a reply



Submit