Linux программирование в примерах | страница 70



>58   return;

>59

>60  printf("\tStack level %d: address of stack_var: %p\n",

>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. Резюме

• У каждой программы Linux и (Unix) есть различные области памяти. Они хранятся в разных частях файла исполняемой программы на диске. Некоторые из секций загружаются при запуске программы в одну и ту же область памяти. Все запушенные экземпляры одной и той же программы разделяют исполняемый код (сегмент текста). Программа >size показывает размеры различных областей переместимых объектных файлов и полностью скомпонованных исполняемых файлов.

• В адресном пространстве запушенной программы могут быть дыры, а размер адресного пространства может изменяться при выделении и освобождении памяти. На современных системах адрес 0 не является частью адресного пространства, поэтому не пытайтесь разыменовывать указатели >NULL.

• На уровне языка С память выделяется с помощью одной из функций >malloc(), >calloc() или >realloc(). Память освобождается с помощью >free(). (Хотя с помощью >realloc() можно делать все, использование ее таким образом не рекомендуется.) Освобожденная память обычно не удаляется из адресного пространства; вместо этого она используется повторно при последующих выделениях.