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

на главную

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

Основную часть функции составляет цикл (строка 12), проходящий через массив значений флагов. Когда флаг найден (строка 13), код вычисляет, сколько места требуется строке (строка 18) и проверяет, осталось ли столько места (строки 19–20).

Тест '

sp ! = buffer
' для первого значения флага завершается неудачей, возвращая 0. Для последующих флагов тест дает значение 1. Это говорит нам, что между значениями должен быть вставлен разделительный символ '
|
'. Добавляя результат (1 или 0) к длине строки, мы получаем правильное значение
space_needed
.
Тот же тест с той же целью проводится в строке 22 для проверки строк 23 и 24, которые вставляют символ '
|
'.

В заключение строки 26–29 копируют значение строки, выверяют количество оставшегося места и обновляют указатель

sp
. Строка 33 возвращает адрес буфера, который содержит печатное представление строки.

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

Более того, статический буфер по определению является буфером фиксированного размера. Что случилось с принципом GNU «никаких произвольных ограничений»?

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

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

На практике фиксированный размер также не является проблемой; мы знаем, что размер

BUFSIZ
достаточен для представления всех флагов, которые мы используем. Тем не менее, поскольку мы опытные и знаем, что вещи могут измениться, в
getflags2str
есть код, предохраняющий себя от переполнения буфера. (Переменная
space_left
и код в строках 18–20.)

В качестве отступления, использование

BUFSIZ
спорно. Эта константа должна использоваться исключительно для буферов ввода/вывода, но часто она используется также для общих строковых буферов. Такой код лучше убрать, определив явные константы, такие, как
FLAGVALSIZE
, и использовав в строке 11 '
sizeof (buffer)
'.

Вот сокращенный сеанс GDB, показывающий использование

flags2str
:

$ gdb gawk /* Запустить GDB с gawk */

GNU gdb 5.3

...

(gdb) break do_print /* Установить контрольную точку */

Breakpoint 1 at 0x805a584: file builtin.c, line 1547.

(gdb) run 'BEGIN { print "hello, world" }' /* Запустить программу */

Starting program: /home/arnold/Gnu/gawk/gawk-3.1.4/gawk 'BEGIN { print "hello, world" }'

Breakpoint 1, do_print (tree=0x80955b8) at builtin.c: 1547 /*
Останова в контрольной точке */

1547 struct redirect *rp = NULL;

(gdb) print *tree /* Вывести NODE */

$1 = {sub = {nodep =

 {1 = {lptr = 0x8095598, param_name = 0x8095598 "xU\t\b",

 ll = 134629464}, r = {rptr = 0x0, pptr = 0, preg = 0x0, hd = 0x0,

 av = 0x0, r_ent =0}, x = {extra = 0x0, xl = 0, param_list = 0x0},

 name = 0x0, number = 1, reflags = 0), val = {

 fltnum = 6.6614606209589101e-316, sp = 0x0, slen = 0, sref = 1,

 idx = 0}, hash = {next = 0x8095598, name = 0x0, length = 0, value = 0x0,

 ref = 1}}, type = Node_K_print, flags = 1}

(gdb) print flags2str(tree->flags) /* Вывести значение флага */

$2 = 0x80918a0 "MALLOC"

(gdb) next /* Продолжить */

1553 fp = redirect_to_fp(tree->rnode, &rp);

...

1588 efwrite(t[i]->stptr, sizeof(char), t[i]->stlen, fp, "print", rp, FALSE);

(gdb) print *t[i] /* Снова вывести NODE */

$4 = {sub = {nodep =

 {l = {lptr = 0x8095598, parm_name = 0x8095598 "xU\t\b",

 ll = 134829464}, r = {rptr = 0x0, pptr = 0, preg = 0x0, hd = 0x0,

 av = 0x0, r_ent =0), x = {extra = 0x8095ad8, xl = 134830808,

 param_list = 0x8095ad8}, name = 0xc <Address 0xc out of bounds>,

 number = 1, reflags = 4294967295}, val = {

 fltnum = 6.6614606209589101e-316, sp = 0x8095ad8 "hello, world",

 slen = 12, sref = 1, idx = -1}, hash = {next = 0x8095598, name = 0x0,

 length = 134830808, value = 0xc, ref = 1}}, type = Node_val, flags = 29}

(gdb) print flags2str(t[i]->flags) /* Вывести значение флага */

$5 = 0x80918a0 "MALLOC|PERM|STRING|STRCUR"

Надеемся, вы согласитесь, что настоящий механизм общего назначения значительно более элегантный и более простой в использовании, чем первоначальный.

Тщательное проектирование и использование массивов структур часто может заменить или слить воедино повторяющийся код.

15.4.1.5. По возможности избегайте объединений

«Не бывает бесплатных обедов»

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

Камень. Книга пятая

Минин Станислав
5. Камень
Фантастика:
боевая фантастика
6.43
рейтинг книги
Камень. Книга пятая

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

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

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Отверженный. Дилогия

Опсокополос Алексис
Отверженный
Фантастика:
фэнтези
7.51
рейтинг книги
Отверженный. Дилогия

Неудержимый. Книга XIII

Боярский Андрей
13. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XIII

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

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

Начальник милиции. Книга 3

Дамиров Рафаэль
3. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 3

На границе империй. Том 9. Часть 2

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

Лорд Системы 13

Токсик Саша
13. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 13

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Вторая невеста Драконьего Лорда. Дилогия

Огненная Любовь
Вторая невеста Драконьего Лорда
Любовные романы:
любовно-фантастические романы
5.60
рейтинг книги
Вторая невеста Драконьего Лорда. Дилогия

Неудержимый. Книга X

Боярский Андрей
10. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга X

Гарем вне закона 18+

Тесленок Кирилл Геннадьевич
1. Гарем вне закона
Фантастика:
фэнтези
юмористическая фантастика
6.73
рейтинг книги
Гарем вне закона 18+

В зоне особого внимания

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