【问题标题】:exception propagation in externally linked C libraries外部链接的 C 库中的异常传播
【发布时间】:2010-12-19 22:11:09
【问题描述】:

我正在编写一个使用外部第三方 C 库的 C++ 库。所以我的库会调用这个第三方库中的函数,第三方库会回调到我库的不同部分。

我想知道在这种情况下异常会发生什么? 假设 MyLib::foo() 调用外部 C 库函数,该函数最终调用 MyLib::bar(),bar 抛出异常,会发生什么?异常是否会正确传播到 foo() 中的处理程序?

谢谢!

【问题讨论】:

    标签: c++ c exception external libraries


    【解决方案1】:

    异常是否会正确传播到foo() 中的处理程序?

    我认为异常是否通过外部 C 代码传播是未定义的。更糟糕的是,C 代码毫无准备,无法处理异常。 C 代码不需要对突然的、意外的返回免疫,所以它不知道 RAII 等。

    当我曾经遇到这种情况时,我在返回 C API 之前捕获了异常,将其存储,并在调用从 C API 返回时重新抛出它。

    【讨论】:

    • 这比我的回答要好。我没有看到第三方库是C而不是C++。即使提问者多次提到这一点。睡觉时间,也许吧。
    • 这是正确答案。虽然一些实现 (GNU) 竭尽全力尝试允许异常在 C 代码中传播,但利用它是一个非常非常糟糕的想法。它不仅不可移植,而且没有理由假设其间的 C 代码不会有不一致的状态或持有尚未在外部记录或释放的内存分配。最好的情况是您要求内存泄漏,最坏的情况是随机崩溃。我喜欢 sbi 关于如何解决该问题的建议,但最好完全避免跨模块边界抛出异常。
    • @Tommy:我写了很长的解释,为什么让异常通过 C 库传播作为对您答案的评论是不好的,并且当您在我想提交评论时已经删除它时变得脾气暴躁。因此,感谢您的精彩评论,弥补了这一点。 :)
    【解决方案2】:

    这是一个沉重的平台实现细节。通常,异常管道很可能能够通过 C 函数激活帧展开堆栈。这是必要的,因为 CRT 通常是用 C 编写的。但是,C 代码不太可能对此感到满意,状态发生了突变,无法恢复。

    以防万一这是 Windows,C 代码确实可以使用它。 C++ 异常依赖于 Windows 内置的通用异常支持,称为结构化异常处理 (SEH)。您使用 __try 和 __except 关键字来调用可以恢复 C 代码状态的异常过滤器。显然这是不可移植的。

    请不要在不提及实施细节的情况下提出实施细节问题。

    【讨论】:

      【解决方案3】:

      阅读(并购买!)Herb Sutter 的 C++ Coding Standards

      #62: 不允许异常传播 跨越模块边界。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-26
        • 1970-01-01
        相关资源
        最近更新 更多