c++ - 这个 "trick"跨 DLL 边界抛出异常是个坏主意吗?

标签 c++ exception dll

我正在构建一个共享库,我希望它在不同编译器(如 Windows 上的 MSVC 和 GCC)之间兼容 ABI。我的灵感来自 this blog post .我唯一错过的是跨 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 边界进行编码,在客户端代码端打包回异常,然后重新抛出。

关于c++ - 这个 "trick"跨 DLL 边界抛出异常是个坏主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30760348/

相关文章:

JAVA。我收到 'unreported exception' 编译器错误

exception - 为什么 length/2 让我退出全局堆栈?

c - 调试可能从 Windows 服务调用的 Windows DLL

c++ - gnat gprbuild : how to build a dynamic dll and link with a static c++ library

c - 调试 Visual Studio 2010 DLL 项目

c++ - 如何从文本文件中读取数据并将其加载到 vector 中?

c++ - 通过2个字段查找特定对象的 vector 元素

c++ - 有条件地调用 cv::VideoCapture 构造函数

c++ - 位没有被重置?

Java 自定义异常处理