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

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

Жанры

Linux программирование в примерах
Шрифт:

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
).

• В качестве одного операнда выражения сравнения (

==
,
<
и т.д.), с целой константой в качестве другого операнда. Выражение сравнения может быть единственный контролирующим выражением цикла или условного оператора.

• В качестве операнда унарного оператора '

!
', причем результирующее выражение является единственным контролирующим выражением цикла или условного оператора.

• В качестве всего выражения оператора-выражения, возможно, приведенного к типу

void
. Например:

(void)setjmp(buf);

В-третьих, если вы хотите изменить локальную переменную в функции, которая вызывает

setjmp
, после вызова и хотите, чтобы эта переменная сохранила свое последнее присвоенное после
longjmp
значение, нужно объявить эту переменную как
volatile
. В противном случае все локальные переменные, не являющиеся
volatile
и изменившиеся после того, как была первоначально вызвана
setjmp
, имеют неопределенные значения. (Обратите внимание, что сама переменная
jmp_buf
не должна объявляться как
volatile
.) Например:

1 /* ch12-setjmp.с --- демонстрирует setjmp/longjmp и volatile. */

2

3 #include <stdio.h>

4 #include <setjmp.h>

5

6 jmp_buf env;

7

8 /* comeback --- выполнение longjmp */

9

10 void comeback(void)

11 {

12 longjmp(env, 1);

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

Локки 7. Потомок бога

Решетов Евгений Валерьевич
7. Локки
Фантастика:
аниме
эпическая фантастика
фэнтези
5.00
рейтинг книги
Локки 7. Потомок бога

Последний Герой. Том 1

Дамиров Рафаэль
1. Последний герой
Фантастика:
попаданцы
альтернативная история
фантастика: прочее
5.00
рейтинг книги
Последний Герой. Том 1

Аландский крест

Перунов Антон
5. Константин
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Аландский крест

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

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

Кодекс Охотника XXXI

Винокуров Юрий
31. Кодекс Охотника
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Охотника XXXI

Японский городовой

Зот Бакалавр
7. Героями не становятся, ими умирают
Фантастика:
фэнтези
попаданцы
5.80
рейтинг книги
Японский городовой

Ярар. Начало

Грехов Тимофей
1. Ярар
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ярар. Начало

Император Пограничья 1

Астахов Евгений Евгеньевич
1. Император Пограничья
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 1

Печать пожирателя 6

Соломенный Илья
6. Пожиратель
Фантастика:
городское фэнтези
попаданцы
аниме
сказочная фантастика
фантастика: прочее
5.00
рейтинг книги
Печать пожирателя 6

Матабар

Клеванский Кирилл Сергеевич
1. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар

Имперец. Том 1 и Том 2

Романов Михаил Яковлевич
1. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Имперец. Том 1 и Том 2

Черный Маг Императора 19

Герда Александр
19. Черный маг императора
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 19

Уникум

Поселягин Владимир Геннадьевич
1. Уникум
Фантастика:
альтернативная история
4.60
рейтинг книги
Уникум

Звездная Кровь. Изгой III

Елисеев Алексей Станиславович
3. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой III