Linux программирование в примерах | страница 61
Например, GNU awk (gawk) использует эту методику. Выдержка из файла >awk.h
в дистрибутиве >gawk
(слегка отредактировано, чтобы уместилось на странице):
>#define getnode(n) if (nextfree) n = nextfree, \
> nextfree = nextfree->nextp; else n = more_nodes()
>#define freenode(n) ((n)->flags = 0, (n)->exec_count = 0,\
> (n)->nextp = nextfree, nextfree = (n))
Переменная >nextfree
указывает на связанный список структур NODE. Макрос >getnode()
убирает из списка первую структуру, если она там есть. В противном случае она вызывает >more_nodes()
, чтобы выделить новый список свободных структур >NODE
. Макрос >freenode()
освобождает структуру >NODE
, помещая его в начало списка.
ЗАМЕЧАНИЕ. Первоначально при написании своего приложения делайте это простым способом: непосредственно используйте >malloc()
и >free()
. Написание собственного распределителя вы должны рассмотреть лишь в том и только в том случае, если профилирование вашей программы покажет, что она значительную часть времени проводит в функциях выделения памяти.
3.2.1.8. Пример: чтение строк произвольной длины
Поскольку это, в конце концов, Программирование на Linux в примерах, настало время для примера из реальной жизни. Следующий код является функцией >readline()
из GNU Make 3.80 (>ftp://ftp.gnu.org/gnu/make/make-3.80.tar.gz
). Ее можно найти в файле >read.c
.
Следуя принципу «никаких произвольных ограничений», строки в >Makefile
могут быть любой длины. Поэтому главной задачей этой процедуры является чтение строк произвольной длины и гарантирование того, что они помещаются в используемый буфер.
Вторичной задачей является распоряжение продлением строк. Как и в С, строки, заканчивающиеся обратным слешем, логически продолжаются со следующей строки. Используется стратегия поддержания буфера. В нем хранится столько строк, сколько помещается в буфер, причем указатели отслеживают начало буфера, текущую строку и следующую строку. Вот структура:
>struct ebuffer {
> char *buffer; /* Начало текущей строки в буфере. */
> char *bufnext; /* Начало следующей строки в буфере. */
> char *bufstart; /* Начало всего буфера. */
> unsigned int size; /* Размер буфера для malloc. */
> FILE *fp; /* Файл или NULL, если это внутренний буфер. */
> struct floc floc; /* Информация о файле в fp (если он есть). */
>};
Поле >size
отслеживает размер всего буфера, a >fp
является указателем типа >FILE
для файла ввода. Структура floc не представляет интереса при изучении процедуры.