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

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

Жанры

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

соответствующее действие. */

 switch (error_code) {

 case EPERM: /* Доступ запрещен. */

 case EROFS: /* Переменная PATH ссылается на файловую

систему, доступную только для чтения. */

 case ENAMETOOLONG: /* Переменная PATH оказалась слишком длинной. */

 case ENOENT: /* Переменная PATH ссылается на

несуществующий
файл. */

 case ENOTDIR: /* Один из компонентов переменной PATH

не является каталогом. */

 case EACCES: /* Один из компонентов переменной PATH

недоступен. */

/* Что-то неправильно с файлом, выводим сообщение

об ошибке. */

fprintf(stderr, "error changing ownership of %s: %s\n",

path, strerror(error_code));

/* He завершаем программу; можно предоставить пользователю

шанс открыть другой файл. */

break;

 case ЕFAULT:

/* Переменная PATH содержит неправильный адрес. Это, скорее

всего, ошибка программы. */

abort;

 case ENOMEM:

/* Ядро столкнулось с нехваткой памяти. */

fprintf(stderr, "%s\n", strerror(error_code));

exit(1);

 default:

/* Произошла какая-то другая, непредвиденная ошибка. Мы

пытались обработать все возможные коды ошибок. Если

что-то пропущено, то это ошибка программы! */

abort;

 };

}

В самом начале программного фрагмента можно было поставить следующий код:

rval = chown(path, user_id, -1);

assert(rval == 0);

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

2.2.4. Ошибки выделения ресурсов

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

return
код ошибки вызывающему модулю.

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

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

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

1. выделяет буфер;

2. открывает файл;

3. читает содержимое файла и записывает его в буфер;

4. закрывает файл;

5. возвращает буфер вызывающему модулю.

Если файл не существует, этап 2 закончится неудачей. Подходящая реакция в этом случае — вернуть из функции значение

NULL
. Но если буфер уже был выделен на этапе 1, существует опасность потери этого ресурса. Нужно не забыть освободить буфер где-то в программе. Если же неудачей завершится этап 3, требуется не только освободить буфер перед выходом из функции, но и закрыть файл.

В листинге 2.6 показан пример реализации такой функции.

Листинг 2.6. (readfile.c) Освобождение ресурсов при возникновении аварийных ситуаций

#include <fcntl.h>

#include <stdlib.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <unistd.h>

char* read_from_file(const char* filename, size_t length) {

 char* buffer;

 int fd;

 ssize_t bytes_read;

 /* Выделяем буфер. */

 buffer = (char*)malloc(length);

 if (buffer == NULL)

return NULL;

 /* Открываем файл. */

 fd = open(filename, O_RDONLY);

 if (fd == 1) {

/* Открыть файл не удалось. Освобождаем буфер

перед выходом. */

free(buffer);

return NULL;

 }

 /* Чтение данных. */

 bytes_read = read(fd, buffer, length);

 if (bytes_read != length) {

/* Чтение не удалось. Освобождаем буфер и закрываем файл

перед выходом. */

free(buffer);

close(fd);

return NULL;

 }

 /* Все прошло успешно. Закрываем файл и возвращаем буфер

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

Избранное

Лукницкий Павел Николаевич
Проза:
советская классическая проза
5.00
рейтинг книги
Избранное

История политических и правовых учений. Шпаргалки

Князева Светлана Александровна
Зачет
Научно-образовательная:
обществознание
юриспруденция
государство и право
шпаргалки
6.00
рейтинг книги
История политических и правовых учений. Шпаргалки

Точка Бифуркации XII

Смит Дейлор
12. ТБ
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Точка Бифуркации XII

Сборник "Этические уравнения"

Головачев Василий Васильевич
Фантастика:
научная фантастика
4.75
рейтинг книги
Сборник Этические уравнения

Мечников. Из доктора в маги

Алмазов Игорь
1. Жизнь Лекаря с нуля
Фантастика:
альтернативная история
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Мечников. Из доктора в маги

Качество, эффективность, нравственность

Гличев Александр Владимирович
Научно-образовательная:
учебники
5.00
рейтинг книги
Качество, эффективность, нравственность

Технарь

Муравьёв Константин Николаевич
1. Технарь
Фантастика:
космическая фантастика
попаданцы
7.13
рейтинг книги
Технарь

Безудержная страсть

Кузьминых Юлия
Любовные романы:
современные любовные романы
6.25
рейтинг книги
Безудержная страсть

Собрание сочинений в шести томах. Том 6

Кочетов Всеволод Анисимович
Проза:
советская классическая проза
5.00
рейтинг книги
Собрание сочинений в шести томах. Том 6

Пламенев. Книга X

Карелин Сергей Витальевич
10. Пламенев
Фантастика:
аниме
уся
сказочная фантастика
фэнтези
фантастика: прочее
5.00
рейтинг книги
Пламенев. Книга X

Гимн Непокорности

Злобин Михаил
2. Хроники геноцида
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Гимн Непокорности

Большой Сочи. История Кавказа

Андреев Александр Радьевич
Приключения:
путешествия и география
5.00
рейтинг книги
Большой Сочи. История Кавказа

Держава Света (сборник)

Рерих Николай Константинович
Религия и эзотерика:
эзотерика
5.00
рейтинг книги
Держава Света (сборник)

Официант-бармен. Пособие для учащихся средних профессионально-технических училищ

Барановский Виктор Александрович
Научно-образовательная:
прочая научная литература
5.00
рейтинг книги
Официант-бармен. Пособие для учащихся средних профессионально-технических училищ