Linux программирование в примерах | страница 71



• Необходимо предпринять чрезвычайные меры осторожности в следующих случаях

 • освобождать лишь память, выделенную с помощью соответствующих процедур,

 • освобождать память один и только один раз,

 • освобождать неиспользуемую память и

 • не допускать «утечки» динамически выделяемой памяти.

• POSIX предоставляет для удобства функцию >strdup(), a GLIBC предоставляет функции >getline() и >getdelim() для чтения строк произвольной длины. Функции интерфейса низкоуровневых системных вызовов >brk() и >sbrk() предоставляют непосредственный, но примитивный доступ к выделению и освобождению памяти. Если вы не создаете свой собственный распределитель памяти, следует избегать их. Существует функция >alloca() для выделения памяти в стеке, но ее использование не рекомендуется. Подобно умению распознавать ядовитый плющ, про нее нужно знать лишь для того, чтобы избегать ее.

Упражнения

1. Начав со структуры —

>struct line {

> size_t buflen;

> char *buf;

> FILE* fp;

>};

— напишите свою собственную функцию >readline(), которая будет читать строки любой длины. Не беспокойтесь о строках, продолженных с помощью обратного слеша. Вместо использования >fgetc() для чтения строк используйте >getc() для чтения одного символа за раз.

2. Сохраняет ли ваша функция завершающий символ конца строки? Объясните, почему.

3. Как ваша функция обрабатывает строки, оканчивающиеся CR-LF?

4. Как вы инициализируете структуру? В отдельной процедуре? С помощью документированных условий для определенных значений в структуре?

5. Как вы обозначаете конец файла? Как вы указываете, что возникла ошибка ввода/вывода? Должна ли ваша функция сообщать об ошибках? Объясните, почему.

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

7. Перепишите вашу функцию с использованием >fgets() и протестируйте ее. Является ли новый код более сложным или менее сложным? Какова его производительность по сравнению с версией >getc()?

8. Изучите страницу справки V7 для end(3) (>/usr/man/man3/end.3 в дистрибутиве V7). Пролила ли она свет на то, как может работать '>sbrk(0)'?

9. Усовершенствуйте >ch03-memaddr.c так, чтобы она печатала расположение аргументов и переменных окружения. В какой области адресного пространства они находятся?

Глава 4

Файлы и файловый ввод/вывод

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