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:
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.
Answers to questions are automatically generated and may not have been reviewed.
Learn about nested exceptions in C++: from basic concepts to advanced handling techniques