Как стать автором
Обновить

Реализация механизма исключений средствами языка C

Время на прочтение 1 мин
Количество просмотров 1.4K
Программисты C++, Java, C#… при написании кода на «чистом» C часто сталкиваются с проблемой отсутствия механизма исключений. Классический способ обработки ошибок в C — проверка кодов возврата. В сложных алгоритмах при глубокой вложенности это весьма неудобно. Приведенный ниже способ не нов, но, к сожалению, многие с ним не знакомы.

Итак, в POSIX есть пара полезных функций: setjmp и longjmp

#include <setjmp.h>

int setjmp(jmp_buf env);
void longjmp(jmp_buf evn, int val);


Рассмотрим пример:


#include <setjmp.h>
jmp_buf jbuf;

/* ...... */

/* Ставим обработчик */
int result = setjmp(jbuf);
switch(result) {
   case 0: /* это блок try */
   case 1: /* Один из блоков catch */
   case 2: /* Еще один catch */
};

/* .... */

/* Здесь мы хотим кинуть исключение */
longjmp(jbuf, КОД_ИСКЛЮЧЕНИЯ);


Вызов setjmp сохраняет состояние стека в переменную. При сохранении setjmp возвращает 0. Эту переменную необходимо сделать доступной для кода, который будет инициировать переход. После вывода longjmp всё будет выглядеть так, как будто setjmp вернул отличное от 0 значение.

Что стоит отметить:
1) longjmp никогда не возвращает управление. Либо будет откат к setjmp, либо, если jmp_buf битый — segmentation fault.
2) Второй параметр longjmp — то значение, которое вернет setjmp по восстановлении стека. 0 передать не получится (в этом случае вернется 1).
3) Описанный выше механизм ломает «нормальную логику» работы программы на C. При этом в некоторых случая может сделать программу более читаемой. К этому стоит относиться как к goto.

UPDATE-замечание от mraleph:
Строго говоря setjmp не сохраняет «состояние стека». Он сохраняет лишь значения регистров, поэтому в частности jmp_buf'ом нельзя пользоваться, если функция, в которой он был создан завершилась…
Теги:
Хабы:
+2
Комментарии 8
Комментарии Комментарии 8

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн