当抛出异常的代码与使用-fno-exceptions编译的库链接时会发生什么?
具体而言,我想知道GCC会如何确保在与使用-fno-exceptions
编译的代码链接时如何引发异常行为。当抛出异常的代码与使用-fno-exceptions编译的库链接时会发生什么?
GNU libstdc++
说明书以下here。
之前详述
-fno-exceptions
库的支持,首先在当使用该标志失去的东西通过的纸币:它会破坏异常试图通过与-fno-exceptions
编译代码,代码是否有任何try
或catch
结构体。如果您可能会抛出一些代码,则不应使用-fno-exceptions
。如果您有一些使用try
或catch
的代码,则不应使用-fno-exceptions
。
这听起来像是一句话:“你不应该......”也就是说。未定义的行为。
在另一方面,我从this SO question的印象是,一切都是犹太只要用-fno-exceptions
编译的代码不throw
,try
,或catch
(显然是一个编译时错误)和异常从未通过函数传播从这个图书馆。这是有道理的:为什么图书馆编译-fno-exceptions
只要不与其功能交互就抛出异常?
我做了一些修补,发现如果我使用GCC 7.1.1编译一个简单的程序,其中一个源文件编译为-fno-exceptions
,另一个引发并捕获异常,则所有编译,链接和运行都正常。但这并不意味着这种行为是有保证的;它仍然可能是未定义的。
我的动机是,我有一种情况,我将自己的应用程序代码与使用-fno-exceptions
构建的库链接起来,并根据对所述库调用的函数调用,在我的即使该异常不通过库的函数传播,自己的代码也会立即导致段错误。它听起来像是图书馆里的一个bug,但我认为在编译过程中通过-fno-exceptions
时可以这样做。
GCC的actual reference on code-generation flags提到-fexceptions
相对简短,并不回答我的问题。任何人都知道另一个参考/有相关经验?
更新:我从源重建库,这次打开异常支持。段错误依然存在!时间为错误报告。
由于链接问题指出,GCC 需要允许-fno-exceptions
和-fexceptions
为了链接C和C++而共存。
从更理论上讲,异常问题与程序的调用图密切相关。这是一个有向图(调用者/被调用者),但它可以是循环的,节点之间可以有多条边。现在每个函数/节点都可以编译,有或没有例外。我们可以将一个安全程序定义为一个程序,其中没有“有例外”节点可以从“无例外”节点到达。
这可能是不必要的严格 - 在try...catch(...) { }
块内的C++位代码应该可以从C代码调用看起来是合理的。但我不知道GCC的保证。并考虑它的含义 - 调用图与调用堆栈相关。调用堆栈通常形成从main()
到当前正在执行的函数的路径。如果整个路径都是异常感知的,那么异常是安全的。但是,如果有一个函数不知道异常,它可能会使堆栈处于一个不能安全处理异常的状态,如果堆栈展开不会展开那么远,则可以使用甚至。
我想说你认为没有明确声明'-fno-exceptions'和'-fexceptions'是兼容的,但它是隐含的。然而(这里有一个疯狂的观点),你确定你在抛出异常时没有通过任何库代码。可能发生的显而易见的'隐藏'方式是在堆栈展开中调用(或未调用或未命中)的'-fno-exceptions'析构函数。只是一个想法。 – Persixty
我不认为这就是我的情况,因为即使我把'throw'直接放在'main'的'try' /'catch'中作为测试,segfault仍然会出现。它永远不允许传播足够多的触发任何析构函数。当我读到你的建议时,我只是做了一个双倍的工作。我当然没有想到这种可能性! –
不客气。只是抛出你的想法。我对gcc并不熟悉,当然也不是更奇特的配置。这些文档肯定是这样写的:“这里有一大堆的事情是为了解决异常的问题。 – Persixty