跨 DLL 边界抛出异常"trick"是一个坏主意吗?
Is this "trick" to throw exceptions across DLL boundaries a bad idea?
我正在构建一个共享库,我希望在不同的编译器(如Windows上的MSVC和GCC)之间实现ABI兼容。我从这篇博文中获得了灵感。我唯一错过的是跨 DLL 边界抛出异常的能力......所以我做了这个小技巧:
我的图书馆.hpp
class Thrower{
static void(*m_thowFunc)(const char*);
public:
static void setThrowFunction(void(*func)(const char*)){
m_thowFunc = func;
}
static void throwException(const char* msg){
m_thowFunc(msg);
}
};
extern "C" {
EXPORT void MyLibrary_setThrowFunction(void(*func)(const char*));
EXPORT void MyLibrary_foo();
}
我的图书馆.cpp
extern "C" {
EXPORT void MyLibrary_setThrowFunction(void(*func)(const char*)){
Thrower::setThrowFunction(func);
}
EXPORT void MyLibrary_foo(){
Thrower::throwException("oops, an error occured...");
}
}
并在客户端代码中
void defaultThrowFunction(const char* msg){
throw std::runtime_error(msg);
}
int main(){
MyLibrary_setThrowFunction(&defaultThrowFunction);
try{
MyLibrary_foo();
}catch(std::runtime_error& e){
//handle exception
}
}
这就像一个魅力。我可以在客户端代码中处理从 DLL(实际上是由客户端代码引发)引发的异常。我知道的唯一缺点是我在编译 DLL 时有大量警告,因为"并非所有控制路径都返回值"......
我在这里错过了什么吗?这真的是一个好主意吗?
这可能有效,但前提是两个代码库的抛出机制和堆栈展开代码基本相同且兼容。
为了在抛出后销毁它应该销毁的每个对象,客户端代码必须能够理解 DLL 代码如何设置其堆栈以及在哪里注册要清理的析构函数等。 如果幸运的话,您的客户端和 DLL 代码编译器可能已经足够一致,可以正常工作。
哪种破坏了你的设计要点。
可能有效的方法是仔细封送 DLL 边界上的异常。
DLL 的"C"API 返回有关引发哪些异常(如果有)的信息。 客户端编译的仅C++头文件包装器调用"C"API,在客户端编译的代码中检测异常,解包并引发异常。
在DLL内部,"C"API执行try{}catch(){}
,并调用内部C++库。 catch
子句将异常信息填充到"C"API 返回值中,然后返回。
现在,内部异常被抛出,在C++ DLL中捕获,在"C"API中封送DLL边界,打包回客户端代码端的异常,然后重新抛出。
通常,跨 DLL 边界引发异常是一个坏主意,除非一切都在您的完全控制之下。
我的意思是:抛出器和捕获器应该使用相同的编译器版本、相同的标准库和相同的运行时实例。所有这些事情都可以抛弃异常处理 - 希望只是崩溃,但可能会有一个更不幸的微妙结果。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 定义一个带有缓冲区的函数作为卤化物中的边界框参数
- 为什么打印数组边界外的值不会给我一个错误
- 我如何定义一个全局函数来检查边界
- 解引用一个超出边界50%的指针(数组的数组)
- 更改线看起来像一个箭头- c++构建器边界
- 如何确定一个顶点是否在边界上的网格在CGAL
- 跨 DLL 边界抛出异常"trick"是一个坏主意吗?
- 是否有一个函数来获得一个QImage的非白色区域的边界框