- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Linux программирование в примерах - Арнольд Роббинс
Шрифт:
Интервал:
Закладка:
Функцию sbrk() использовать проще; ее аргумент является числом байтов, на которое нужно увеличить адресное пространство. Вызвав ее с приращением 0, можно определить, где в настоящее время заканчивается адресное пространство. Таким образом, чтобы увеличить адресное пространство на 32 байта, используется код следующего вида:
char *p = (char*)sbrk(0); /* получить текущий конец адресного
пространства */
if (brk(p + 32) < 0) {
/* обработать ошибку */
}
/* в противном случае, изменение сработало */
Практически, вам не нужно непосредственно использовать brk(). Вместо этого используется исключительно sbrk() для увеличения (или даже сокращения) адресного пространства. (Вскоре мы покажем, как это делать, в разделе 3.2.5. «Исследование адресного пространства».)
Еще более практично вообще никогда не использовать эти процедуры. Программа, которая их использует, не может затем использовать также и malloc(), и это создает большую проблему, поскольку многие элементы стандартной библиотеки полагаются на использование malloc(). Поэтому использование brk() или sbrk() может приводить к трудно обнаруживаемым крушениям программы.
Но знать о низкоуровневых механизмах стоит, и конечно же, набор функций malloc() реализован с помощью sbrk() и brk().
3.2.4. Вызовы ленивых программистов: alloca()
«Опасность, Билл Робинсон! Опасность!»
- Робот -Есть еще одна дополнительная функция выделения памяти, о которой вам нужно знать. Мы обсуждаем ее лишь для того, чтобы вы поняли ее, когда увидите, но не следует использовать ее в новых программах! Эта функция называется alloca(); она объявлена следующим образом:
/* Заголовок в GNU/Linux, возможно, не на всех Unix-системах */
#include <alloca.h> /* Обычный */
void *alloca(size_t size);
Функция alloca() выделяет size байтов из стека. Хорошо, что выделенная память исчезает после возвращения из функции. Нет необходимости явным образом освобождать память, поскольку это осуществляется автоматически, как в случае с локальными переменными.
На первый взгляд, alloca() выглядит чем-то типа панацеи для программистов, можно выделять память, о которой можно вовсе не беспокоиться. Подобно Темной Стороне Силы, это, конечно, привлекает. И подобным же образом этого нужно избегать по следующим причинам:
• Функция не является стандартной; она не включена ни в какой стандарт, ни в ISO, ни в С или POSIX.
• Функция не переносима. Хотя она существует на многих системах Unix и GNU/Linux, она не существует на не-Unix системах. Это проблема, поскольку код часто должен быть многоплатформенным, выходя за пределы просто Linux и Unix.
• На некоторых системах alloca() невозможно даже реализовать. Весь мир не является ни процессором Intel x86, ни GCC.
• Цитируя справку[45] (добавлено выделение): «Функция alloca зависит от машины и от компилятора. На многих системах ее реализация ошибочна. Ее использование не рекомендуется».
• Снова цитируя справку: «На многих системах alloca не может быть использована внутри списка аргументов вызова функции, поскольку резервируемая в стеке при помощи alloca память оказалась бы в середине стека в пространстве для аргументов функции».
• Она потворствует неряшливому программированию. Тщательная и корректная работа с памятью не сложна; вам просто нужно подумать о том, что вы делаете, и планировать заранее.
GCC обычно использует встроенную версию функции, которая действует с использованием внутритекстового (inline) кода. В результате есть другие последствия alloca(). Снова цитируя справку:
Факт, что код является внутритекстовым (inline), означает, что невозможно получить адрес этой функции или изменить ее поведение путем компоновки с другой библиотекой.
Внутритекстовый код часто состоит из одной инструкции, подгоняющей указатель стека, и не проверяет переполнение стека. Поэтому нет возврата NULL при ошибке.
Справочная страница не углубляется в описание проблемы со встроенной alloca() GCC. Если есть переполнение стека, возвращаемое значение является мусором. И у вас нет способа сообщить об этом! Это упущение делает невозможным использование GCC alloca() в устойчивом коде.
Все это должно убедить вас избегать alloca() в любом новом коде, который вы пишете. В любом случае, если приходится писать переносимый код с использованием malloc() и free(), нет причины в использовании также и alloca().
3.2.5. Исследование адресного пространства
Следующая программа, ch03-memaddr.c, подводит итог всему, что мы узнали об адресном пространстве. Она делает множество вещей, которые не следует делать на практике, таких, как вызовы alloca() или непосредственные вызовы brk() и sbrk().
1 /*
2 * ch03-memaddr.с --- Показать адреса секций кода, данных и стека,
3 * а также BSS и динамической памяти.
4 */
5
6 #include <stdio.h>
7 #include <malloc.h> /* для определения ptrdiff_t в GLIBC */
8 #include <unistd.h>
9 #include <alloca.h> /* лишь для демонстрации */
10
11 extern void afunc(void); /* функция, показывающая рост стека */
12
13 int bss_var; /* автоматически инициализируется в 0, должна быть в BSS */
14 int data_var = 42; /* инициализируется в не 0, должна быть
15 в сегменте данных */
16 int
17 main(int argc, char **argv) /* аргументы не используются */
18 {
19 char *p, *b, *nb;
20
21 printf("Text Locations:n");
22 printf("tAddress of main: %pn", main);
23 printf("tAddress of afunc: %pn", afunc);
24
25 printf("Stack Locations.n");
26 afunc();
27
28 p = (char*)alloca(32);
29 if (p != NULL) {
30 printf("tStart of alloca()'ed array: %pn", p);
31 printf("tEnd of alloca()'ed array: %pn", p + 31);
32 }
33
34 printf("Data Locations:n");
35 printf("tAddress of data_var: %pn", &data_var);
36
37 printf("BSS Locations:n");
38 printf("tAddress of bss_var: %pn", &bss_var);
39
40 b = sbrk((ptrdiff_t)32); /* увеличить адресное пространство */
41 nb = sbrk((ptrdiff_t)0);
42 printf("Heap Locations:n");
43 printf("tInitial end of heap: %pn", b);
44 printf("tNew end of heap: %pn", nb);
45
46 b = sbrk((ptrdiff_t)-16); /* сократить его */
47 nb = sbrk((ptrdiff_t)0);
48 printf("tFinal end of heap: %pn", nb);
49 }
50
51 void
52 afunc(void)
53 {
54 static int level = 0; /* уровень рекурсии */
55 auto int stack_var; /* автоматическая переменная в стеке */
56
57 if (++level == 3) /* избежать бесконечной рекурсии */
58 return;
59
60 printf("tStack level %d: address of stack_var: %pn",
61 level, &stack_var);
62 afunc(); /* рекурсивный вызов */
63 }
Эта программа распечатывает местонахождение двух функций main() и afunc() (строки 22–23). Затем она показывает, как стек растет вниз, позволяя afunc() (строки 51–63) распечатать адреса последовательных экземпляров ее локальной переменной stack_var. (stack_var намеренно объявлена как auto, чтобы подчеркнуть, что она находится в стеке.) Затем она показывает расположение памяти, выделенной с помощью alloca() (строки 28–32). В заключение она печатает местоположение переменных данных и BSS (строки 34–38), а затем памяти, выделенной непосредственно через sbrk() (строки 40–48). Вот результаты запуска программы на системе Intel GNU/Linux:
$ ch03-memaddr
Text Locations:
Address of main: 0x804838c
Address of afunc: 0x80484a8
Stack Locations:
Stack level 1: address of stack_var: 0xbffff864
Stack level 2: address of stack_var: 0xbffff844
/* Стек растет вниз */
Start of alloca()'ed array: 0xbffff860
End of alloca()'ed array: 0xbffff87f
/* Адреса находятся в стеке */
Data Locations:
Address of data_var: 0x80496b8
BSS Locations:
Address of bss_var: 0x80497c4
/* BSS выше инициализированных данных */
Heap Locations:
Initial end of heap: 0x80497c8
/* Куча непосредственно над BSS */
New end of heap: 0x80497e8
/* И растет вверх */
Final end of heap: 0x80497d8
/* Адресные пространства можно сокращать */
3.3. Резюме

