Propagating Nested Exceptions Across DLL Boundaries
Can I throw a nested exception from a function in a DLL and catch it in the calling code?
Propagating exceptions, including nested exceptions, across DLL (dynamically linked library) boundaries is possible but requires careful design.
The main challenge is that the DLL and the calling code might use different memory allocators. If an exception is allocated in the DLL using the DLL's allocator, but then caught and deallocated in the calling code using the calling code's allocator, it can lead to runtime errors or memory corruption.
To safely propagate exceptions across DLL boundaries:
- The DLL and the calling code should use the same C++ runtime library, to ensure they use the same memory allocator.
- The exception types should be defined in a header file that is shared between the DLL and the calling code, to ensure they have the same definition.
- The exception types should have a non-throwing destructor, to avoid the issues with throwing destructors mentioned in the previous answer.
- The DLL function should catch any internal exceptions and translate them into error codes or exceptions that are part of the DLL's public interface.
Here's an example:
// DLL.cpp
#include <stdexcept>
#include "SharedTypes.h"
// SharedTypes.h
struct DLLException : std::exception {
const char* what() const noexcept override {
return "Exception from DLL"; }
};
extern "C" __declspec(dllexport)
void DLLFunction() {
try {
// Some operation that might throw
throw std::runtime_error{"Internal error"};
} catch (...) {
std::throw_with_nested(DLLException{});
}
}
// Main.cpp
#include <iostream>
#include "SharedTypes.h"
int main() {
try {
DLLFunction();
} catch (const DLLException& e) {
std::cout << "Caught DLLException: "
<< e.what() << '\n';
std::rethrow_if_nested(e);
} catch (const std::exception& e) {
std::cout << "Caught nested exception: "
<< e.what() << '\n';
}
}
In this design, the DLLFunction
catches any internal exceptions and wraps them in a DLLException
, which is defined in a shared header file. The main
function can then catch DLLException
and access any nested exceptions.
However, even with this design, there are still potential pitfalls. For maximum portability and safety, it's often better for DLL functions to return error codes instead of throwing exceptions.
Nested Exceptions
Learn about nested exceptions in C++: from basic concepts to advanced handling techniques