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

3.2.5. Исследование адресного пространства

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
  /* Адресные пространства можно сокращать */

Оглавление книги


Генерация: 1.211. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз