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

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

Жанры

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

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

Шрифт:

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

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

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

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

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

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

13 printf("This line is never printed\n");

14 }

15

16 /* main - вызов setjmp, действия с переменными, вывод значений */

17

18 int main(void)

19 {

20 int i = 5;

21 volatile int j = 6;

22

23 if (setjmp(env) == 0) { /* первый раз */

24 i++;

25 j++;

26 printf("first time: i = %d, j = %d\n", i, j);

27 comeback));

28 } else /* второй раз */

29 printf("second time: i = %d, j = %d\n", i, j);

30

31 return 0;

32 }

В этом примере сохранение своего значения ко второму вызову

printf
гарантируется
лишь
j (строка 21). Значение (строка 20) в соответствии со стандартом С 1999 г. не определено. Это может быть 6, может быть 5, а может даже какое-нибудь другое значение!

В-четвертых, как описано в разделе 12.5.2 «Обработка масок сигналов:

sigsetjmp
и
siglongjmp
», стандарт С 1999 г. не делает никаких утверждений о влиянии, если оно есть,
setjmp
и
longjmp
на состояние сигналов программы. Если это важно, вам придется вместо них использовать
sigsetjmp
и
siglongjmp
.

В-пятых, эти процедуры содержат поразительные возможности для утечек памяти! Рассмотрим программу, в которой

main
вызывает
setjmp
, а затем
вызывает несколько вложенных функций, каждая из которых выделяет с помощью
malloc
динамическую память. Если наиболее глубоко вложенная функция делает
longjmp
обратно в
main
, указатели на динамическую память теряются. Взгляните на
ch12-memleak.c
:

1 /* ch12-memleak.с --- демонстрирует утечки памяти с помощью setjmp/longjmp. */

2

3 #include <stdio.h>

4 #include <malloc.h> /* для определения ptrdiff_t в GLIBC */

5 #include <setjmp.h>

6 #include <unistd.h>

7

8 jmp_buf env;

9

10 void f1(void), f2(void);

11

12 /* main --- утечка памяти с помощью setjmp и longjmp */

13

14 int main(void)

15 {

16 char *start_break;

17 char *current_break;

18 ptrdiff_t diff;

19

20 start_break = sbrk((ptrdiff_t)0);

21

22 if (setjmp(env) == 0) /* первый раз */

23 printf("setjmp called\n");

24

25 current_break = sbrk((ptrdiff_t) 0);

26

27 diff = current_break - start_break;

28 printf("memsize = %ld\n", (long)diff);

29

30 f1;

31

32 return 0;

33 }

34

35 /* f1 --- выделяет память, осуществляет вложенный вызов */

36

37 void f1(void)

38 {

39 char *p = malloc(1024);

40

41 f2;

42 }

43

44 /* f2 --- выделяет память, выполняет longjmp */

45

46 void f2(void)

47 {

48 char *p = malloc(1024);

49

50 longjmp(env, 1);

51 }

Эта программа устанавливает бесконечный цикл, используя

setjmp
и
longjmp
. Строка 20 использует для нахождения текущего начала кучи
sbrk
(см. раздел 3.2.3 «Системные вызовы:
brk
и
sbrk
»), а затем строка 22 вызывает
setjmp
. Строка 25 получает текущее начало кучи; это место каждый раз изменяется, поскольку
longjmp
повторно входит в код. Строки 27–28 вычисляют, сколько было выделено памяти, и выводят это количество. Вот что происходит при запуске:

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

Мастер Разума V

Кронос Александр
5. Мастер Разума
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Мастер Разума V

Последний из рода Демидовых

Ветров Борис
Фантастика:
детективная фантастика
попаданцы
аниме
5.00
рейтинг книги
Последний из рода Демидовых

Любовь Носорога

Зайцева Мария
Любовные романы:
современные любовные романы
9.11
рейтинг книги
Любовь Носорога

Авиатор: назад в СССР 12

Дорин Михаил
12. Покоряя небо
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Авиатор: назад в СССР 12

Толян и его команда

Иванов Дмитрий
6. Девяностые
Фантастика:
попаданцы
альтернативная история
7.17
рейтинг книги
Толян и его команда

Академия

Кондакова Анна
2. Клан Волка
Фантастика:
боевая фантастика
5.40
рейтинг книги
Академия

Изгой. Пенталогия

Михайлов Дем Алексеевич
Изгой
Фантастика:
фэнтези
9.01
рейтинг книги
Изгой. Пенталогия

Неудержимый. Книга IX

Боярский Андрей
9. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга IX

Невеста

Вудворт Франциска
Любовные романы:
любовно-фантастические романы
эро литература
8.54
рейтинг книги
Невеста

Энфис 2

Кронос Александр
2. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 2

Убийца

Бубела Олег Николаевич
3. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Убийца

Лорд Системы

Токсик Саша
1. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
4.00
рейтинг книги
Лорд Системы

Делегат

Астахов Евгений Евгеньевич
6. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Делегат

Невеста напрокат

Завгородняя Анна Александровна
Любовные романы:
любовно-фантастические романы
6.20
рейтинг книги
Невеста напрокат