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

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

Жанры

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

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

Шрифт:

unlink(tfile);

free(tfile);

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

12.4. Совершение самоубийства:

abort

Бывают моменты, когда программа просто не может продолжаться. Обычно лучше всего при этом выдать сообщение об ошибке и вызвать

exit
. Однако, особенно для ошибок, являющихся проблемами программирования, полезно не только завершиться, но и создать дамп ядра, который сохраняет в файле состояние работающей
программы для последующего исследования в отладчике. В этом заключается работа функции
abort
:

#include <stdlib.h> /* ISO С */

void abort(void);

Функция

abort
посылает сигнал
SIGABRT
самому процессу. Это случится, даже если
SIGABRT
заблокирован или игнорируется. После этого осуществляется обычное для
SIGABRT
действие, которое заключается в создании дампа ядра.

Примером

abort
в действии является макрос
assert
, описанный в начале данной главы. Когда
assert
обнаруживает, что его выражение ложно, он выводит сообщение об ошибке, а затем вызывает
abort
для создания дампа ядра.

В соответствии со стандартом С, осуществляет

abort
очистку или нет, зависит от реализации. Под GNU/Linux она выполняет очистку: все потоки
<stdio.h> FILE*
перед завершением программы закрываются. Обратите, однако, внимание, что для открытых файлов, использующих системные вызовы на основе дескрипторов файлов, ничего не делается. (Если открыты лишь файлы или каналы, ничего не нужно делать. Хотя мы не обсуждали это, дескрипторы файлов используются также для сетевых соединений, и оставление их открытыми является плохой практикой.)

12.5. Нелокальные переходы

«Идите прямо в тюрьму. Не проходите GO. Не забирайте 200$».

– Монополия -

Вы, без сомнения, знаете, чем является

goto
: передачей потока управления на метку где-то в текущей функции. Операторы
goto
при скупом употреблении могут послужить удобочитаемости и правильности функции (Например, когда все проверки ошибок используют
goto
для перехода на метку в конце функции, такую, как
clean_up
, код с этой меткой проводит очистку [закрывая файлы и т.п.] и возвращается.) При плохом использовании операторы
goto
могут привести к так называемой «лапше» в коде, логику которого становится невозможно отследить.

Оператор

goto
в языке С ограничен переходом на метку в текущей функции. Многие языки в семействе Алгола, такие, как Паскаль, допускают использование
goto
для выхода из вложенной функции в предшествующую вызывающую функцию. Однако в С нет способа, в пределах синтаксиса самого языка, перейти в определенную точку другой функции, пусть даже и вызывающей. Такой переход называется нелокальным переходом.

Почему полезен нелокальный переход? Рассмотрите интерактивную программу, которая считывает и выполняет программы. Предположим, пользователь запускает длительное задание, разочаровывается или меняет мнение о данном задании и нажимает CTRL-С для генерирования сигнала

SIGINT
. Когда запускается обработчик сигнала, он может перейти обратно в начало главного цикла чтения и обработки команд. Строковый редактор ed представляет простой пример этого:

$ ed -p '> ' sayings /*
Запуск ed, '> ' используется как приглашение */

sayings: No such file or directory

> a /* Добавить текст */

Hello, world

Don't panic

^C /* Сгенерировать SIGINT */

? /* Сообщение об ошибке ''один размер подходит всем'' */

> 1,$p /* ed возвращается в командную строку */

Hello, world /* '1,$p' prints all the lines */

Don't panic

> w /* Сохранить файл */

25

> q /* Все сделано */

Внутри себя

ed
устанавливает перед циклом команд точку возврата, и обработчик сигнала осуществляет нелокальный переход на эту точку возврата.

12.5.1. Использование стандартных функций:

setjmp
и
longjmp

Нелокальные переходы осуществляются с помощью функций

setjmp
и
longjmp
. Эти функции используются в двух разновидностях. Традиционные процедуры определены стандартом ISO С:

#include <setjmp.h> /* ISO С */

int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

Тип

jmp_buf
определен через
typedef
в
<setjmp.h>
.
setjmp
сохраняет текущее «окружение» в
env
.
env
обычно является глобальной или статической на уровне файла переменной, так что она может использоваться из вызванной функции. Это окружение включает любую информацию, необходимую для перехода на местоположение, из которого была вызвана
setjmp
. Содержание
jmp_buf
по своей природе машинно-зависимо; таким образом,
jmp_buf
является непрозрачным типом: тем, что вы используете, не зная, что находится внутри него.

setjmp
возвращает 0, когда она вызывается для сохранения в
jmp_buf
текущего окружения. Ненулевое значение возвращается, когда с использованием окружения осуществляется нелокальный переход:

jmp_buf command_loop; /* На глобальном уровне */

/* ... затем в main ... */

if (setjmp(command_loop) == 0) /* Состояние сохранено, продолжить */

 ;

else /* Мы попадаем сюда через нелокальный переход */

 printf("?\n"); /* ed's famous message */

/* ... теперь начать цикл команд ... */

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

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

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

Дамиров Рафаэль
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
рейтинг книги
Призыватель нулевого ранга