Выброс C++ исключение через вызов функции C

У меня есть три свободные функции: F0, F1 и F2. F0 вызывает F1, который, в свою очередь, вызывает F2.

F0 и F2 являются C++ функциями, где F1 является функцией C. F2 подвергается воздействию F1 через: extern "C"

Код для каждой из свободных функций выглядит следующим образом:

~~~~ F0.cpp ~~~~

void f0()
{
   try
   {
      f1();
   }
   catch (...)
   {}
}

~~~~ F0.cpp ~~~~


~~~~ F1.c ~~~~

void f1()
{
   f2();
}

~~~~ F1.c ~~~~


~~~~ F2.cpp ~~~~

void f2()
{
  throw 1
}

~~~~ F2.cpp ~~~~

Вопрос:

Исправлено ли в f2 исключение, прошедшее через f1 и правильно пойманное в f0?

Или std :: неожиданно вызывается из-за того, что исключение не обрабатывается, или все это должно быть неопределенным поведением? - если это так, где в стандарте говорится об обработке исключений в этом конкретном контексте.


Обратите внимание, что речь идет не об обработке исключений в C, а о том, что происходит в ситуации, когда исключение может протекать через уровень C (если вообще) и быть пойманным на вызывающем C++ уровне - и любые возникающие побочные эффекты и т.д.

Ответ 1

Это специфичный для платформы и специфический для компилятора вопрос.

Например, в Linux/GCC вам необходимо скомпилировать C-код с -fexceptions, после чего разматывать таблицы будут сборки, а исключение - с помощью кода C.

Из https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/Code-Gen-Options.html#index-fexceptions

-fexceptions

Включить обработку исключений. Создает дополнительный код, необходимый для распространения исключений. Для некоторых целей это означает, что GCC генерирует информацию о распаковке кадра для всех функций, что может привести к значительным накладным расходам данных, хотя это не влияет на выполнение. Если вы не укажете этот параметр, GCC позволяет по умолчанию использовать такие языки, как C++, которые обычно требуют обработки исключений, и отключает его для таких языков, как C, которые обычно не требуют этого. Однако вам может понадобиться включить этот параметр при компиляции кода C, который должен правильно взаимодействовать с обработчиками исключений, написанными в C++. Вы также можете отключить этот параметр, если вы компилируете старые C++ программы, которые не используют обработку исключений.

Я менее знаком с разработкой Visual C++/Windows, но считаю, что обработка исключений будет использовать общие механизмы, если вы скомпилируете свой код C++ и C с параметром /EHa (разрешите смешивание структурированных и C++ исключений)

Ответ 2

Вы можете легко это сделать, вместо использования компилятора C для компиляции вы можете использовать компилятор C++.

#include <stdio.h>
#include <stdexcept>

void blablabla () {
    throw std::runtime_error ("BLA BLA BLA");
}

int main ()
try {
    blablabla();
} catch (std::runtime_error& e) {
    printf("%s\n", e.what());                                                                                                 
} catch (...) {
    printf ("Unknown excetpion");
}

и выход:

BLA BLA BLA

Все, что мне нужно сделать, запускается после g++ myfile.c &&./a.out и gcc myfile.c &&./a.out. Этот шаг будет зависеть от вашего компьютера, компилятора и настройки.

Таким образом, вы можете поймать исключение C++ в своем C коде, все, что вам нужно сделать, это скомпилировать его как C++. Если вы знаете, что что-то бросает исключение, вы можете просто поймать его в C коде. Представьте, что если blablabla() находится где-то в библиотеке, которую вы используете, вы можете просто написать:

int main (void) {
    try {
       blablabla ();
    } catch (NameOfException& e) {
       std::cout << e.what() << "\n";
    }
}