C++ 使用“-fno-exceptions”,“new T”会发生什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6049563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:24:15  来源:igfitidea点击:

With "-fno-exceptions", what happens with "new T"?

c++exception

提问by Johannes Schaub - litb

I was wondering, will new Tstill throw bad_allocif I compile my program using the -fno-exceptionsoption to disable exception handling?

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

Or will the compiler (GCC and clang support that option) implicitly transform the use of new Tto new (nothrow) T?

还是编译器(GCC 和 clang 支持该选项)会隐式转换new Tto的使用new (nothrow) T

采纳答案by nos

I can't give a definitive answer to all the perks around -fno-exceptions, just the observations on a 32 bit linux machine, gcc 4.5.1 - bad_alloc is thrown with and without -fno-exceptions

我无法给出关于 -fno-exceptions 的所有好处的明确答案,只是在 32 位 linux 机器上的观察结果,gcc 4.5.1 - 有和没有抛出 bad_alloc -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

回答by Matthijs Kooijman

The way I understand it, operator newis defined by libstdc++. If you now compile your own code with -fno-exceptions, you cannot catch any exceptions, but you will still be linking against the normal version of libstdc++, which does throw an exception.

我理解它的方式operator new是由 libstdc++ 定义的。如果您现在使用 编译您自己的代码-fno-exceptions,您将无法捕获任何异常,但您仍将链接到 libstdc++ 的正常版本,它确实会引发异常。

So yes, new Twill throw an exception, even with -fno-exception.

所以是new T的,即使使用-fno-exception.

However, if you compiled libstdc++ with -fno-exceptionas well, things become different. Now, new Tcannot throw an exception but, if I read the libstdc++ manual rightit will call abort()instead.

然而,如果你也编译了 libstdc++ -fno-exception,事情就变得不一样了。现在,new T不能抛出异常,但是,如果我正确阅读了 libstdc++ 手册,它将abort()改为调用。

It seems that, if you want your new Tto return NULL on failure, the only way is to explicitely specify nothrow...

似乎,如果您希望new T在失败时返回 NULL,唯一的方法是明确指定nothrow...

回答by Michael Kristofik

It's not a definitive answer, but the GCC Manual(see the section "Doing Without") has this:

这不是一个明确的答案,但GCC 手册(请参阅“没有做”一节)有这个:

Before detailing the library support for -fno-exceptions, first a passing note on the things lost when this flag is used: it will break exceptions trying to pass through code compiled with -fno-exceptionswhether or not that code has any try or catch constructs. If you might have some code that throws, you shouldn't use -fno-exceptions.

在详细介绍对 的库支持之前-fno-exceptions,首先要说明使用此标志时丢失的东西:-fno-exceptions无论该代码是否具有任何 try 或 catch 构造,它都会打破尝试通过编译代码的异常。如果您可能有一些抛出的代码,则不应使用 -fno-exceptions.

The way I read that, you might have to explicitly ask for the nothrow version of newto be completely safe.

根据我的阅读方式,您可能必须明确要求 的 nothrow 版本new是完全安全的。

回答by supercat

In many exception-handling systems, if routine "foo" calls "bar", which in turn calls "moo", and "moo" throws an exception, the only way that exception can cleanly make it back to "foo" is if "bar" has code to handle the exception. Even if "bar" is going to let the exception propagate uncaught, it will generally have to ensure that its local variables get properly destroyed before execution is allowed to leave scope. This will require adding extra code to "bar"; in most systems, some of that code will have to execute even if no exception is thrown.

在许多异常处理系统中,如果例程“foo”调用“bar”,后者又调用“moo”,而“moo”抛出异常,则异常可以干净地使其回到“foo”的唯一方法是如果“ bar”具有处理异常的代码。即使“bar”会让异常传播未被捕获,它通常也必须确保在允许执行离开范围之前正确销毁其局部变量。这将需要向“bar”添加额外的代码;在大多数系统中,即使没有抛出异常,其中一些代码也必须执行。

BTW, on some ARM processors like the Cortex M3, or like the Arm7 running in ARM mode, if the caller is also going to be running in ARM mode, one could allow for exceptions without any execution-time cost by having a "normal" subroutine return go to LR+4 (four bytes beyond the normal return address) and have an exceptional exit go to LR (which would then be a 4-byte branch instruction). Such behavior would be contrary to normal practice on the ARM, though, and such a design would not port nicely to the Cortex M0.

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