`std :: terminate` вызов в функции` noexcept` с ограниченной видимостью - gcc vs clang codegen - PullRequest
0 голосов
/ 26 апреля 2018

Рассмотрим следующий фрагмент кода:

void f();

void a()          { f(); }
void b() noexcept { f(); }

В приведенном выше сценарии тело f не отображается компилятору в текущей единице перевода. Поэтому, поскольку b помечено noexcept, для стороны, выполняющей вызов, должен быть сгенерирован дополнительный код, чтобы убедиться, что исключение перехвачено и std::terminate вызвано.

Это то, что clang++ -Ofast -std=c++2a делает (версия транка) :

a(): # @a()
  jmp f() # TAILCALL
b(): # @b()
  push rax
  call f()
  pop rax
  ret
  mov rdi, rax
  call __clang_call_terminate
__clang_call_terminate: # @__clang_call_terminate
  push rax
  call __cxa_begin_catch
  call std::terminate()

Однако g++ -Ofast -std=c++2a не (версия с транком) :

a():
  jmp f()
b():
  jmp f()

живой пример на godbolt.org


Как g++ это сходит с рук? Разве не должен генерироваться код на стороне вызывающей стороны, поскольку тело f не видно?

... или это просто странная причуда Compiler Explorer?

1 Ответ

0 голосов
/ 28 июня 2018

Как ответил @ach, в трекере ошибок gcc открыта ошибка . Но, если можно так сказать, это не главная проблема.

В результате происходит утечка исключения вместо завершения программы, но:

  • если вы хотите завершить вызов по необработанному исключению, это уже имеет место
  • если вам нужна гарантия безопасности исключений без бросков, то она не предоставляется.

Единственный случай, о котором я могу подумать, это во время разработки. Или в условиях, в которых обязательно произойдет сбой, если контракт нарушен (когда на карту поставлена ​​жизнь); в этом случае компиляторы и используемые функции строго контролируются.

Анджей делает хороший пример в своей статье - нет, кроме - зачем?

...