对于“-fno-Exception”,“ new T”会发生什么?

我想知道,如果我使用 -fno-exceptions选项来禁用异常处理来编译我的程序,new T还会抛出 bad_alloc吗?

或者编译器(GCC 和 clang 支持该选项)会隐式地将 new T的使用转换为 new (nothrow) T吗?

30411 次浏览

这并不是一个明确的答案,但是 海湾合作委员会手册(参见“不做”一节)有以下内容:

在详细说明库支持之前 对于 -fno-exceptions,首先传球 注意这面旗子丢失的东西 使用: 它将打破异常 试图通过编译的代码 与 -fno-exceptions是否 那个代码有任何 try 或 catch 如果你有一些 抛出的代码,你不应该使用 -fno-exceptions.

在我看来,您可能必须明确要求使用 nothrow 版本的 new才是完全安全的。

我不能给出一个确定的答案周围的所有津贴-fno-异常,只是在32位 linux 机器上的观察,gcc 4.5。1-bad _ alloc 抛出了 -fno-exceptions和没有 -fno-exceptions

[21:38:35 1 ~/tmp] $ cat bad_alloc.cpp


int main()
{
char* c = new char[4000000000U];
}
[21:38:58 1 ~/tmp] $ g++ bad_alloc.cpp
[21:39:06 1 ~/tmp] $ ./a.out
terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc
Aborted
[21:39:07 1 ~/tmp] $ g++ -fno-exceptions bad_alloc.cpp
[21:39:16 1 ~/tmp] $ ./a.out
terminate called after throwing an instance of 'std::bad_alloc'
what():  std::bad_alloc
Aborted

在许多异常处理系统中,如果例程“ foo”调用“ bar”,后者又调用“ moo”,并且“ moo”抛出一个异常,那么异常能够干净利落地返回到“ foo”的唯一方法是,如果“ bar”有处理异常的代码。即使“ bar”允许异常未捕获地传播,它通常也必须确保在允许执行离开作用域之前正确地销毁其本地变量。这将需要在“ bar”中添加额外的代码; 在大多数系统中,即使没有抛出异常,其中一些代码也必须执行。

顺便说一句,在一些 ARM 处理器上,比如 Cortex M3,或者在 ARM 模式下运行的 Arm7,如果调用者也将在 ARM 模式下运行,我们可以允许异常,而没有任何执行时间的成本,通过一个“正常”子例程返回到 LR + 4(比正常返回地址多4个字节) ,并且有一个异常退出到 LR (这将是一个4字节的分支指令)。这样的行为将违背正常的做法在 ARM,但是,这样的设计不会很好地移植到皮层 M0。

在我看来,operator new是由 libstdc + + 定义的。如果您现在使用 -fno-exceptions编译自己的代码,就不能捕获任何异常,但是仍然会链接到普通版本的 libstdc + + ,它会抛出异常。

因此,是的,即使使用 -fno-exceptionnew T也会抛出异常。

但是,如果也使用 -fno-exception编译 libstdc + + ,情况就不同了。现在,new T不能抛出异常,但是,如果我读取 使用 libstdc + + 手动右键,它将调用 abort()

看起来,如果您希望您的 new T在失败时返回 NULL,唯一的方法是显式地指定 nothrow..。