【问题标题】:What happens when code that throws exceptions is linked against a library compiled with -fno-exceptions?当抛出异常的代码链接到使用 -fno-exceptions 编译的库时会发生什么?
【发布时间】:2018-02-06 17:24:56
【问题描述】:

具体来说,我想知道 GCC 对抛出异常的代码在链接到使用 -fno-exceptions 编译的代码时的行为做出了哪些保证(如果有的话)。

GNU libstdc++ 手册说以下here

在详细说明库对-fno-exceptions 的支持之前,首先要说明一下使用此标志时丢失的内容:无论该代码是否有任何@987654328,它都会破坏尝试通过使用-fno-exceptions 编译的代码的异常@ 或 catch 构造。如果你可能有一些抛出的代码,你不应该使用-fno-exceptions。如果您的某些代码使用了trycatch,则不应使用-fno-exceptions

这听起来像是“你不应该......”的声明,即未定义的行为。

另一方面,我对this SO question 的印象是,只要使用-fno-exceptions 编译的代码不是throwtrycatch(显然是编译时错误)和异常永远不会通过这个库中的函数传播。这是有道理的:为什么使用-fno-exceptions 编译的库要关心是否抛出异常,只要它们不与其函数交互?

我做了一些修改,发现如果我使用 GCC 7.1.1 编译一个简单的程序,其中一个源文件使用 -fno-exceptions 编译,另一个抛出并捕获异常,一切都可以编译、链接并运行良好.但这并不意味着这种行为是有保证的;它可能仍然是未定义的。

我在这一切中的动机是我有一种情况,我将自己的应用程序代码与使用-fno-exceptions 构建的库链接,并且根据对所述库进行的函数调用,在即使该异常没有通过库的函数传播,我自己的代码也会立即导致段错误。对我来说,这闻起来像是库中的错误,但我认为在编译期间传递 -fno-exceptions 时,这可能是允许的。

GCC 的actual reference on code-generation flags 相对简短地提到了-fexceptions,并没有回答我的问题。有人知道其他参考/有相关经验吗?

更新:我从源代码重建了库,这次启用了异常支持。段错误仍然存​​在!是时候报告错误了。

【问题讨论】:

  • 我会说您认为没有明确声明 -fno-exceptions-fexceptions 兼容但这是隐含的是正确的。但是(这是一个疯狂的点)你确定当你抛出异常时你没有通过任何库代码。可能发生的明显“隐藏”方式是在堆栈展开时调用(或未调用或未调用)-fno-exceptions 析构函数。只是一个想法。
  • 我不认为这就是我的情况,因为即使我将 throw 直接放入 try/catch 中的 main 作为测试,仍然会发生段错误.它永远不允许传播到足以触发任何析构函数。不过,当我读到你的建议时,我只是做了一个双重考虑。我当然没有想到这种可能性!
  • 不客气。只是向你抛出想法。我对 gcc 不太熟悉,当然也不是更奇特的配置。文档肯定读起来像“这里有一堆半途而废的东西来做禁用异常的非常糟糕的事情。警告购买者”。

标签: c++ exception gcc segmentation-fault compiler-flags


【解决方案1】:

正如链接的问题所指出的那样,GCC 需要允许-fno-exceptions-fexceptions 共存,以便链接 C 和 C++。

在更理论的层面上,异常问题与程序的调用图密切相关。这是一个有向图(调用者/被调用者),但它可以是循环的,并且节点之间可以有多个边。现在每个函数/节点都可以在有或没有例外的情况下进行编译。我们可以将安全程序定义为一个程序,其中没有“有异常”节点可以从“无异常”节点到达。

这可能是不必要的严格 - try...catch(...) { } 块中的 C++ 位代码应该可以从 C 代码调用似乎是合理的。但我不知道 GCC 的保证。并考虑它的含义 - 调用图与调用堆栈相关。调用堆栈通常形成从main() 到当前执行函数的路径。如果整个路径是异常感知的,那么异常是安全的。但是,如果有一个函数不知道异常,它可能会将堆栈置于无法安全处理异常的状态,即使如果堆栈展开不会展开那么远。 p>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    相关资源
    最近更新 更多