Подтвердить что ты не робот

С "-fno-exceptions", что происходит с "новым T"?

Мне было интересно, будет ли new T бросать bad_alloc, если я скомпилирую свою программу с помощью параметра -fno-exceptions, чтобы отключить обработку исключений?

Или компилятор (GCC и clang поддерживают эту опцию) неявно преобразуют использование new T в new (nothrow) T?

4b9b3361

Ответ 1

Я не могу дать окончательный ответ на все преимущества вокруг -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

Ответ 2

Как я понимаю, operator new определяется libstdС++. Если теперь вы компилируете свой собственный код с помощью -fno-exceptions, вы не можете поймать никаких исключений, но вы все равно будете ссылаться на обычную версию libstdС++, которая генерирует исключение.

Итак, да, new T выдаст исключение даже с -fno-exception.

Однако, если вы скомпилировали libstdС++ с помощью -fno-exception, все станет по-другому. Теперь new T не может генерировать исключение, но если я прочитаю руководство пользователя libstdС++, оно вместо этого будет называть abort().

Кажется, что если вы хотите, чтобы ваш new T возвращал NULL при ошибке, единственный способ - явно указать nothrow...

Ответ 3

Это не окончательный ответ, но Руководство GCC (см. раздел "Doing Without" ) имеет следующее:

Перед подробным описанием поддержки библиотеки для -fno-exceptions, сначала обратите внимание на вещи, утраченные, когда этот флаг используется: он прерывает исключения пытаясь пройти через скомпилированный код с -fno-exceptions, независимо от того, этот код имеет любую попытку или уловку строит. Если у вас могут быть некоторые код, который бросает, вы не должны использовать -fno-exceptions.

Как я читал это, вам может потребоваться явно запросить полную версию new.

Ответ 4

Во многих системах обработки исключений, если подпрограмма "foo" вызывает "бар" , которая, в свою очередь, вызывает "moo", а "moo" генерирует исключение, единственный способ, которым это исключение может чисто вернуть к "foo", если "бар" имеет код для обработки исключения. Даже если "бар" позволит исключить распространение неотображаемого, он, как правило, должен обеспечить, чтобы его локальные переменные были правильно уничтожены до того, как выполнение разрешено покинуть область видимости. Для этого потребуется добавить дополнительный код в "bar"; в большинстве систем часть этого кода должна выполняться, даже если исключение не выбрано.

BTW, на некоторых ARM-процессорах, таких как Cortex M3, или как Arm7, работающий в режиме ARM, если вызывающий абонент также будет работать в режиме ARM, можно разрешить исключения без каких-либо затрат времени исполнения, Возврат подпрограммы "нормальный" переходит в LR + 4 (четыре байта за нормальный адрес возврата) и имеет исключительный выход в LR (который тогда будет 4-байтовой инструкцией разветвления). Однако такое поведение будет противоречить обычной практике в ARM, и такой дизайн не будет хорошо переноситься на Cortex M0.