Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

Стандарт С утверждает, что даже если

longjmp
вызывается со вторым аргументом, равным 0,
setjmp
по-прежнему возвращает ненулевое значение. В таком случае она возвращает 1.

Возможность передать целое значение и вернуться обратно из

setjmp
полезна; это позволяет коду уровня пользователя различать причину перехода. Например,
gawk
использует эту возможность для обработки операторов
break
и
continue
внутри циклов. (Язык awk осознанно сделан похожим на С в своем синтаксисе для циклов, с использованием
while
,
do-while
,
for
,
break
и
continue
.) Использование
setjmp
выглядит следующим образом (из
eval.c
в дистрибутиве
gawk
3.1.3):

507 case Node_K_while:

508 PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);

509

510 stable_tree = tree;

511 while (eval_condition(stable_tree->lnode)) {

512 INCREMENT(stable_tree->exec_count);

513 switch (setjmp(loop_tag)) {

514 case 0: /* обычный не переход */

515 (void)interpret(stable_tree->rnode);

516 break;

517 case TAG_CONTINUE: /* оператор continue */

518 break;

519 case TAG_BREAK: /* оператор break */

520 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);

521 return 1;

522 default:

523 cant_happen;

524 }

525 }

526 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);

527 break;

Этот фрагмент кода представляет цикл

while
. Строка 508 управляет вложенными циклами посредством стека сохраненных переменных
jmp_buf
. Строки 511–524 выполняют цикл
while
(используя цикл С
while
!). Строка 511 проверяет условие цикла. Если оно истинно, строка 513 выполняет
switch
на возвращаемое значение
setjmp
. Если оно равно 0 (строки 514–516), строка 515 выполняет тело оператора. Однако, когда
setjmp
возвращает
TAG_BREAK
или
TAG_CONTINUE
, оператор
switch
обрабатывает их соответствующим образом (строки 517–518 и 519–521 соответственно).

Оператор

break
на уровне
awk
передает
TAG_BREAK
функции
longjmp
, a
continue
уровня
awk
передает
TAG_CONTINUE
. Снова из
eval.c
с некоторыми пропущенными не относящимися к делу подробностями:

657 case Node_K_break:

658 INCREMENT(tree->exec_count);

/* ... */

675 longjmp(loop_tag, TAG_BREAK);

676 break;

677

678 case Node_K_continue:

679 INCREMENT(tree->exec_count);

/* ... */

696 longjmp(loop_tag, TAG_CONTINUE);

670 break;

Вы

можете думать о
setjmp
как об установке метки, а о
longjmp
как выполнении
goto
с дополнительным преимуществом возможности сказать, откуда «пришел» код (по возвращаемому значению).

12.5.2. Обработка масок сигналов:

sigsetjmp
и
siglongjmp

По историческим причинам, которые, скорее всего, утомили бы вас до слез, стандарт С 1999 г. ничего не говорит о влиянии

setjmp
и
longjmp
на состояние сигналов процесса, а POSIX явно констатирует, что их влияние на маску сигналов процесса (см. раздел 10.6 «Сигналы POSIX») не определено.

Другими словами, если программа изменяет свою маску сигналов процесса между первым вызовом

setjmp
и вызовом
longjmp
, каково состояние маски сигналов процесса после
longjmp
? Та ли эта маска, когда была впервые вызвана
setjmp
? Или это текущая маска? POSIX явно утверждает, что «нет способа это узнать».

Чтобы сделать обработку маски сигналов процесса явной, POSIX ввел две дополнительные функции и один

typedef
:

#include <setjmp.h> /* POSIX */

int sigsetjmp(sigjmp_buf env, int savesigs); /* Обратите внимание:

sigjmp_buf, не jmp_buf! */

void siglongjmp(sigjmp_buf env, int val);

Главным отличием является аргумент

savesigs
функции
sigsetjmp
. Если он не равен нулю, текущий набор заблокированных сигналов сохраняется в
env
вместе с остальным окружением, которое сохраняется функцией
setjmp
.
siglongjmp
с
env
, в которой
savesigs
содержала true, восстанавливает сохраненную маску сигналов процесса

ЗАМЕЧАНИЕ. POSIX также ясен в том, что если

savesigs
равен нулю (false), сохраняется ли маска сигналов процесса или восстанавливается, не определено, как в случае с
setjmp
/
longjmp
. Это, в свою очередь, предполагает, что если собираетесь использовать '
sigsetjmp(env, 0)
', вы также можете не беспокоиться: все дело в том, чтобы иметь контроль над сохранением и восстановлением маски сигналов процесса!

12.5.3. Важные предостережения

Есть несколько технических предостережений, о которых нужно знать.

Во-первых, поскольку сохранение и восстановление среды может быть беспорядочной машинно-зависимой задачей,

setjmp
и
longjmp
могут быть макросами

Во-вторых, стандарт С ограничивает использование

setjmp
следующими ситуациями.

• В качестве единственного контролирующего выражения в операторе цикла или условном операторе (

if
,
switch
).

Поделиться:
Популярные книги

Курсант: назад в СССР

Дамиров Рафаэль
1. Курсант
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Курсант: назад в СССР

Чужая семья генерала драконов

Лунёва Мария
6. Генералы драконов
Фантастика:
фэнтези
5.00
рейтинг книги
Чужая семья генерала драконов

Пышка и Герцог

Ордина Ирина
Фантастика:
юмористическое фэнтези
историческое фэнтези
фэнтези
5.00
рейтинг книги
Пышка и Герцог

Имперский Курьер. Том 5

Бо Вова
5. Запечатанный мир
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Имперский Курьер. Том 5

Имя нам Легион. Том 7

Дорничев Дмитрий
7. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 7

Возвышение Меркурия

Кронос Александр
1. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия

Законы Рода. Том 11

Андрей Мельник
11. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 11

Измена. (Не)любимая жена олигарха

Лаванда Марго
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха

Вираж бытия

Ланцов Михаил Алексеевич
1. Фрунзе
Фантастика:
героическая фантастика
попаданцы
альтернативная история
6.86
рейтинг книги
Вираж бытия

Отмороженный 11.0

Гарцевич Евгений Александрович
11. Отмороженный
Фантастика:
боевая фантастика
рпг
попаданцы
фантастика: прочее
фэнтези
5.00
рейтинг книги
Отмороженный 11.0

История "не"мощной графини

Зимина Юлия
1. Истории неунывающих попаданок
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
История немощной графини

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Газлайтер. Том 15

Володин Григорий Григорьевич
15. История Телепата
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Газлайтер. Том 15

Призыватель нулевого ранга

Дубов Дмитрий
1. Эпоха Гардара
Фантастика:
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Призыватель нулевого ранга