Linux программирование в примерах | страница 64
>84 Позаботиться о сохранении текущего смещения в p. */
>85 more_buffer:
>86 {
>87 unsigned long off = p - start;
>88 ebuf->size *= 2;
>89 start = ebuf->buffer=ebuf->bufstart=(char*)xrealloc(start,
>90 ebuf->size);
>91 p = start + off;
>92 end = start + ebuf->size;
>93 *p = '\0';
>94 }
>95 }
До сих пор мы имели дело с механизмом получения в буфер по крайней мере одной полной строки. Следующий участок обрабатывает случай строки с продолжением. Хотя он должен гарантировать, что конечный символ обратного слеша не является частью нескольких обратных слешей в конце строки. Код проверяет, является ли общее число таких символов четным или нечетным путем простого переключения переменной >backslash
из 0 в 1 и обратно. (Строки 64–70.)
Если число четное, условие '>!backshlash
' (строка 72) будет истинным. В этом случае конечный символ конца строки замещается байтом NUL, и код выходит из цикла.
С другой стороны, если число нечетно, строка содержит четное число пар обратных слешей (представляющих символы \\, как в С), и конечную комбинацию символов обратного слеша и конца строки.[43] В этом случае, если в буфере остались по крайней мере 80 свободных байтов, программа продолжает чтение в цикле следующей строки (строки 78–81). (Использование магического числа 80 не очень здорово; было бы лучше определить и использовать макроподстановку.)
По достижении строки 83 программе нужно больше места в буфере. Именно здесь вступает в игру динамическое управление памятью. Обратите внимание на комментарий относительно сохранения значения >p
(строки 83-84); мы обсуждали это ранее в терминах повторной инициализации указателей для динамической памяти. Значение end также устанавливается повторно. Строка 89 изменяет размер памяти.
Обратите внимание, что здесь вызывается функция >xrealloc()
. Многие программы GNU используют вместо >malloc()
и >realloc()
функции-оболочки, которые автоматически выводят сообщение об ошибке и завершают программу, когда стандартные процедуры возвращают >NULL
. Такая функция-оболочка может выглядеть таким образом:
>extern const char *myname; /* установлено в main() */
>void *xrealloc(void *ptr, size_t amount) {
> void *p = realloc(ptr, amount);
> if (p == NULL) {
> fprintf(stderr, "%s: out of memory!\n", myname);
> exit(1);
> }
> return p;
>}
Таким образом, если функция >xrealloc()
возвращается, она гарантированно возвращает действительный указатель. (Эта стратегия соответствует принципу «проверки каждого вызова на ошибки», избегая в то же время беспорядка в коде, который происходит при таких проверках с непосредственным использованием стандартных процедур.) Вдобавок, это позволяет эффективно использовать конструкцию '