Спецификации исключений

Спецификации исключений — это функция языка C++, которую не рекомендуется использовать в C++11. Они предназначались для предоставления сводных сведений об исключениях, которые может создавать функция, но на практике с этими спецификациями начали возникать проблемы. Действительно полезной оказалась лишь спецификация throw(). Например:

void MyFunction(int i) throw();

сообщает компилятору, что функция не создает исключений. Эта строка эквивалентна использованию атрибута __declspec (nothrow). Его использование не является обязательным. В стандарте ISO C++11 введен оператор noexcept, но поддержка этой функции пока отсутствует в Visual C++.

Visual C++ не соответствует стандарту ISO C++ при реализации спецификаций исключений. В следующей таблице представлены сводные сведения о реализации спецификаций исключений в Visual C++.

Спецификация исключений

Значение

throw()

Функция не вызывает исключений. Однако, если функция, помеченная атрибутом throw(), создает исключение, компилятор Visual C++ не вызывает функцию unexpected (дополнительные сведения см. в разделах unexpected (CRT) и unexpected (<exception>)). Если функция помечена атрибутом throw(), компилятор Visual C++ предполагает, что она не создает исключений C++, и формирует код соответствующим образом. Из-за оптимизации кода, которую может выполнять компилятор C++ (на основе допущения, что функция не создает исключений C++), создание исключения такой функцией может привести к неправильному выполнению программы.

throw(...)

Функция может создавать исключения.

throw(type)

Функция может создавать исключения типа type. Однако в .NET для Visual C++ это интерпретируется как throw(...). См. раздел Спецификаторы исключений функций.

Если в приложении используется обработка исключений, в ней должна быть одна или несколько функций, которые обрабатывают создаваемые исключения. Все функции, вызываемые между функцией, вызывающей исключение, и функцией, которая обрабатывает это исключение, должны быть способны создавать исключения.

Поведение функции относительно создания исключений зависит от следующих факторов.

  • В какой среде выполняется компиляция функции — в C или C++.

  • Какой параметр компилятора /EH вы используете.

  • Задана ли явно спецификация исключений.

Явные спецификации исключений не разрешено использовать для функций C.

В следующей таблице приведены сводные сведения о поведении функции относительно создания исключений.

Функция

/EHsc

/EHs

/EHa

/EHac

Функция C

throw()

throw(...)

throw(...)

throw(...)

Функция C++ без спецификации исключений

throw(...)

throw(...)

throw(...)

throw(...)

Функция C++ со спецификацией исключений throw()

throw()

throw()

throw(...)

throw(...)

Функция C++ со спецификацией исключений throw(...)

throw(...)

throw(...)

throw(...)

throw(...)

Функция C++ со спецификацией исключений throw(type)

throw(...)

throw(...)

throw(...)

throw(...)

Пример

// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>

void handler() {
   printf_s("in handler\n");
}

void f1(void) throw(int) {
   printf_s("About to throw 1\n");
   if (1)
      throw 1;
}

void f5(void) throw() {
   try {
      f1();
   }
   catch(...) {
      handler();
    }
}

// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
//   f1();
// }

void __declspec(nothrow) f2(void) {
   try {
      f1();
   }
   catch(int) {
      handler();
    }
}

// only valid if compiled without /EHc 
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
   f1();
}

int main() {
   f2();

   try {
      f4();
   }
   catch(...) {
      printf_s("Caught exception from f4\n");
   }
   f5();
}
  

См. также

Ссылки

Операторы try, throw и catch (C++)

Обработка исключений С++