Означает ли стандарт С++, что C-linkage функции `noexcept`?
Я не могу найти ничего в стандарте, который заставляет функции, объявленные с extern "C"
быть noexcept
, неявно или явно.
Тем не менее, должно быть ясно, что соглашения о вызове C не могут поддерживать исключения... или это?
Означает ли стандарт это, где-то, что я пропустил? Если нет, почему бы и нет? Он просто оставлен в качестве детали реализации?
Ответы
Ответ 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.