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()
можно делать все, использование ее таким образом не рекомендуется.) Освобожденная память обычно не удаляется из адресного пространства; вместо этого она используется повторно при последующих выделениях.