Исключения в языке C
Пишу небольшую программу на C. Работаю в Code::Blocks. Искал, как можно обрабатывать исключения в языке C, нашёл описание __try __except на docs.microsoft.com, но компилятор почему-то на него ругается. Подскажите, как я могу сделать обработку исключений.
Ответы (1 шт):
В плюсах исключения вызывают деструкторы всех переменных в стеке и возвращаются к области, где это исключение ловится.
В Си деструкторов нет и нет механизма фиксирования и выполнения критических участков, вроде освобождения мютексов, освобождение временной памяти и т.д. Всё остаётся на совести программиста и в его руках.
Возвращение в нужный участок программы и продолжение выполнения в месте, где находится точка фиксация реализована с помощью функции setjmp. Она ловит исключение или фиксирует начальную точку.
Запуск исключения производиться с помощью функции longjmp.
Она может создать только исключение типа int и если программист хочет работать с другим типом, то опять он должен всё это написать сам. Например исключение номер 3 будет означать, что само исключение хранится в структуре номер три.
Вот пример плюсовой, и аналог в Си:
C++
// g++ -std=c++11 mainpp.cpp -o mainpp
# include <iostream>
void fun(void) {
std::cout << u8"fun:начало..."<<std::endl;
throw 666 ; }
int main ( ) {
try {
fun ( ) ; }
catch(int e) {
std::cerr<<u8"Ошибка номер "<<e<<std::endl;
return e ; }
catch ( ... ) {
throw ; } }
C
// gcc -std=c11 main.c -o main
# include <stdio.h>
# include <setjmp.h>
// у каждой нити исключения движутся своим
// путём, по-этому у них отдельные указатели
_Thread_local jmp_buf * gloval_jbp ;
void fun ( void ) {
printf ( u8"fun:начало...\n" ) ;
longjmp ( * gloval_jbp , 666 ) ; }
int main ( ) {
jmp_buf jb ;
jmp_buf * const jbold = gloval_jbp ;
// начала области захвата исключений
gloval_jbp = & jb ;
int exc ;
switch ( ( exc = setjmp ( jb ) ) ) {
case 0 :
fun ( ) ;
// конец области захвата исключений
gloval_jbp = jbold ;
break ;
case 666 :
// конец области захвата исключений
gloval_jbp = jbold ;
printf ( u8"main:поймали исключение №666\n" ) ;
return 666 ;
default :
// нераспознанный номер исключения
// конец области захвата исключений
gloval_jbp = jbold ;
// пускаем обработку исключения дальше
// аналог throw ;
longjmp ( * gloval_jbp , exc ) ; } }