Linux программирование в примерах
Часть 32 из 253 Информация о книге
Справочная страница не углубляется в описание проблемы со встроенной
GCC. Если есть переполнение стека, возвращаемое значение является мусором. И у вас нет способа сообщить об этом! Это упущение делает невозможным использование GCCalloca()в устойчивом коде.alloca()Все это должно убедить вас избегать
в любом новом коде, который вы пишете. В любом случае, если приходится писать переносимый код с использованиемalloca()иmalloc(), нет причины в использовании также иfree().alloca()3.2.5. Исследование адресного пространства
Следующая программа,
, подводит итог всему, что мы узнали об адресном пространстве. Она делает множество вещей, которые не следует делать на практике, таких, как вызовыch03-memaddr.cили непосредственные вызовыalloca()иbrk().sbrk()1 /*2 * ch03-memaddr.с --- Показать адреса секций кода, данных и стека,3 * а также BSS и динамической памяти.4 */56 #include <stdio.h>7 #include <malloc.h> /* для определения ptrdiff_t в GLIBC */8 #include <unistd.h>9 #include <alloca.h> /* лишь для демонстрации */1011 extern void afunc(void); /* функция, показывающая рост стека */1213 int bss_var; /* автоматически инициализируется в 0, должна быть в BSS */14 int data_var = 42; /* инициализируется в не 0, должна быть15 в сегменте данных */16 int17 main(int argc, char **argv) /* аргументы не используются */18 {19 char *p, *b, *nb;2021 printf("Text Locations:\n");22 printf("\tAddress of main: %p\n", main);23 printf("\tAddress of afunc: %p\n", afunc);2425 printf("Stack Locations.\n");26 afunc();2728 p = (char*)alloca(32);29 if (p != NULL) {30 printf("\tStart of alloca()'ed array: %p\n", p);31 printf("\tEnd of alloca()'ed array: %p\n", p + 31);32 }3334 printf("Data Locations:\n");35 printf("\tAddress of data_var: %p\n", &data_var);3637 printf("BSS Locations:\n");38 printf("\tAddress of bss_var: %p\n", &bss_var);3940 b = sbrk((ptrdiff_t)32); /* увеличить адресное пространство */41 nb = sbrk((ptrdiff_t)0);42 printf("Heap Locations:\n");43 printf("\tInitial end of heap: %p\n", b);44 printf("\tNew end of heap: %p\n", nb);4546 b = sbrk((ptrdiff_t)-16); /* сократить его */47 nb = sbrk((ptrdiff_t)0);48 printf("\tFinal end of heap: %p\n", nb);49 }5051 void52 afunc(void)53 {54 static int level = 0; /* уровень рекурсии */55 auto int stack_var; /* автоматическая переменная в стеке */5657 if (++level == 3) /* избежать бесконечной рекурсии */58 return;5960 printf("\tStack level %d: address of stack_var: %p\n",61 level, &stack_var);62 afunc(); /* рекурсивный вызов */63 }Эта программа распечатывает местонахождение двух функций
иmain()(строки 22–23). Затем она показывает, как стек растет вниз, позволяяafunc()(строки 51–63) распечатать адреса последовательных экземпляров ее локальной переменнойafunc(). (stack_varнамеренно объявлена какstack_var, чтобы подчеркнуть, что она находится в стеке.) Затем она показывает расположение памяти, выделенной с помощьюauto(строки 28–32). В заключение она печатает местоположение переменных данных и BSS (строки 34–38), а затем памяти, выделенной непосредственно черезalloca()(строки 40–48). Вот результаты запуска программы на системе Intel GNU/Linux:sbrk()$ <b>ch03-memaddr</b>Text Locations:Address of main: 0x804838cAddress of afunc: 0x80484a8Stack Locations:Stack level 1: address of stack_var: 0xbffff864Stack level 2: address of stack_var: 0xbffff844/* Стек растет вниз */