当抛出异常的代码与使用-fno-exceptions编译的库链接时会发生什么?

问题描述:

具体而言,我想知道GCC会如何确保在与使用-fno-exceptions编译的代码链接时如何引发异常行为。当抛出异常的代码与使用-fno-exceptions编译的库链接时会发生什么?

GNU libstdc++说明书以下here

之前详述-fno-exceptions库的支持,首先在当使用该标志失去的东西通过的纸币:它会破坏异常试图通过与-fno-exceptions编译代码,代码是否有任何trycatch结构体。如果您可能会抛出一些代码,则不应使用-fno-exceptions。如果您有一些使用trycatch的代码,则不应使用-fno-exceptions

这听起来像是一句话:“你不应该......”也就是说。未定义的行为。

在另一方面,我从this SO question的印象是,一切都是犹太只要用-fno-exceptions编译的代码不throwtry,或catch(显然是一个编译时错误)和异常从未通过函数传播从这个图书馆。这是有道理的:为什么图书馆编译-fno-exceptions只要不与其功能交互就抛出异常?

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

我的动机是,我有一种情况,我将自己的应用程序代码与使用-fno-exceptions构建的库链接起来,并根据对所述库调用的函数调用,在我的即使该异常不通过库的函数传播,自己的代码也会立即导致段错误。它听起来像是图书馆里的一个bug,但我认为在编译过程中通过-fno-exceptions时可以这样做。

GCC的actual reference on code-generation flags提到-fexceptions相对简短,并不回答我的问题。任何人都知道另一个参考/有相关经验?

更新:我从源重建库,这次打开异常支持。段错误依然存在!时间为错误报告。

+3

我想说你认为没有明确声明'-fno-exceptions'和'-fexceptions'是兼容的,但它是隐含的。然而(这里有一个疯狂的观点),你确定你在抛出异常时没有通过任何库代码。可能发生的显而易见的'隐藏'方式是在堆栈展开中调用(或未调用或未命中)的'-fno-exceptions'析构函数。只是一个想法。 – Persixty

+2

我不认为这就是我的情况,因为即使我把'throw'直接放在'main'的'try' /'catch'中作为测试,segfault仍然会出现。它永远不允许传播足够多的触发任何析构函数。当我读到你的建议时,我只是做了一个双倍的工作。我当然没有想到这种可能性! –

+2

不客气。只是抛出你的想法。我对gcc并不熟悉,当然也不是更奇特的配置。这些文档肯定是这样写的:“这里有一大堆的事情是为了解决异常的问题。 – Persixty

由于链接问题指出,GCC 需要允许-fno-exceptions-fexceptions为了链接C和C++而共存。

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

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