外部链接的 C 库中的异常传播

Posted

技术标签:

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

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

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

谢谢!

【问题讨论】:

【参考方案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: 不允许异常传播 跨越模块边界。

【讨论】:

以上是关于外部链接的 C 库中的异常传播的主要内容,如果未能解决你的问题,请参考以下文章

MFC 静态链接未解析的外部符号

微信如何唤起外部浏览器打开指定链接

微信如何唤起外部浏览器打开指定链接

Error:LNK2019无法解析的外部符号_sscanf, _vsprintf

即使在添加 def 之后,外部“C”也会给出错误“不允许链接规范”。在头文件中?

类序列化导致外部库中的stackOverflowException