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

Означает ли стандарт С++, что C-linkage функции `noexcept`?

Я не могу найти ничего в стандарте, который заставляет функции, объявленные с extern "C" быть noexcept, неявно или явно.

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

Означает ли стандарт это, где-то, что я пропустил? Если нет, почему бы и нет? Он просто оставлен в качестве детали реализации?

4b9b3361

Ответ 1

Насколько я могу судить, нет никакой гарантии, что функция, определенная с помощью ссылки "C" , не будет генерировать исключения. Стандарт позволяет программе на С++ вызывать внешнюю функцию с помощью языковой привязки "C" и определять функции, написанные на С++, которые имеют связь "C" . Поэтому нет ничего, что помешало бы программе С++ вызывать функцию с языковой связью "C" , которая на самом деле написана на С++ (возможно, в другом компиляторе, хотя это и не нужно). Это было бы странно, но это трудно исключить. Кроме того, я не вижу, где в стандарте говорится, что это приведет к поведению undefined (на самом деле, поскольку стандарт не может определить baavior функции, не написанной на С++, это будет единственное использование, где формально нет undefined).

Как следствие, я думаю, что было бы ошибкой предположить, что связь "C" подразумевает noexcept.

Ответ 2

Um, я предполагаю, что extern "C" просто использует C-linkage, а не C-функцию. Это предотвращает выполнение компилятором С++ name mangling.

Более прямо - предположим, что этот код.

// foo.cpp
extern "C" void foo()
{
    throw 1;
}

// bar.cpp
extern "C" void foo();
void bar()
{
    try
    {
        foo();
    }
    catch (int)
    {
        // yeah!
    }
}

Ответ 3

Нигде нет ничего, что говорило бы о том, что extern "C" являются noexcept. С другой стороны, почти все функции стандартной библиотеки C являются noexcept, если вы делаете что - то странное. Как правило, это сводится к вызову неопределенного поведения, но есть несколько других случаев. Это должны быть все из них:

  • Аргумент указателя на функцию qsort() может бросить; поэтому qsort() может бросить.
  • То же самое относится и к bsearch().
  • Вам разрешено заменить malloc(), realloc() и free(). Если вы это сделаете, они могут бросить.
  • В предыдущем случае также могут strdup() calloc(), fopen(), fclose(), freopen(), system() и strdup(). (strdup() определен, но не гарантированно существует.)
  • setjmp() и catch(...) не смешиваются. По крайней мере одна платформа реализовала longjmp() в качестве логического эквивалента throw jmp_buf, в результате чего catch(...) перехватил его.
  • Неопределенное поведение может бросить. Некоторые системы действительно реализуют * NULL как исключение выброса, которое может быть перехвачено catch(...) даже при компиляции кода на языке Си. Если вы выполняете неопределенное поведение в любом месте, вся программа становится неопределенной, как только путь кода безвозвратно фиксируется для достижения неопределенного поведения, что может привести к сбою функций стандартной библиотеки C.