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

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

Жанры

Программирование для 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;

 }

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

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

Корпорация М.И.Ф. (сборник)

Асприн Роберт Линн
Фантастика:
юмористическая фантастика
8.79
рейтинг книги
Корпорация М.И.Ф. (сборник)

Цикл романов "Целитель". Компиляция. Книги 1-17

Большаков Валерий Петрович
Целитель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Цикл романов Целитель. Компиляция. Книги 1-17

Наследие Маозари 2

Панежин Евгений
2. Наследие Маозари
Фантастика:
попаданцы
рпг
аниме
5.00
рейтинг книги
Наследие Маозари 2

Наследник

Шимохин Дмитрий
1. Старицкий
Приключения:
исторические приключения
5.00
рейтинг книги
Наследник

Черный маг императора 2

Герда Александр
2. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
6.00
рейтинг книги
Черный маг императора 2

Атаман. Гексалогия

Корчевский Юрий Григорьевич
Фантастика:
попаданцы
альтернативная история
историческое фэнтези
8.15
рейтинг книги
Атаман. Гексалогия

Старый, но крепкий 9

Крынов Макс
9. Культивация без насилия
Фантастика:
рпг
уся
фэнтези
сянься
5.00
рейтинг книги
Старый, но крепкий 9

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

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

Кодекс Охотника. Книга XXIV

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

Кондотьер

Листратов Валерий
7. Ушедший Род
Фантастика:
фэнтези
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Кондотьер

Наследник

Майерс Александр
3. Династия
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Наследник

Алекс и Алекс

Афанасьев Семен
1. Алекс и Алекс
Фантастика:
боевая фантастика
6.83
рейтинг книги
Алекс и Алекс

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

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

Кодекс Охотника. Книга XXVII

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