2015-07-31 4 views
0
#include <stdio.h> 
#include <stdlib.h> 

int foo;   /* a staticly allocated variable */ 

int recur(int i) {  /* a recursive function */ 
    int j = i;   /* a stack allocated variable within a recursive function */ 
    printf("recur call (i)%d: [email protected] %lx\n", i, (long unsigned int) &j); /* fix this so it print 
s the address of j */ 
    if (i > 0) { 
     return recur(i-1); 
    } 
    return 0; 
} 

int stuff = 7;   /* a statically allocarted, pre-initialized variable */ 

int main (int argc, char *argv[]) { 
    int i;   /* a stack allocated variable */ 
    char *buf1 = malloc(100); /* dynamically allocate some stuff */ 
    char *buf2 = malloc(100); /* and some more stuff */ 
    char *buf3 = malloc(100); /* and some more stuff */ 
    printf("_main @ %lx\n", (long unsigned int) &main); /* fix to print address of main */ 
    printf("_recur @ %lx\n", (long unsigned int) &recur); /* fix to print address of recur */ 
    printf("main call (i):[email protected] %lx\n", (long unsigned int) &i); /* fix to get address of the s 
tack variable */ 
    printf("_static foo: %lx\n", (long unsigned int) &foo); /* fix to get address of the static v 
ariable */ 
    printf("_static stuff: %lx\n", (long unsigned int) &stuff); /* fix to get address of a stati 
c variable */ 
    printf("Heap: malloc 1: %lx\n", (long unsigned int) buf1); 
    printf("Heap: malloc 2: %lx\n", (long unsigned int) buf2); 
    printf("Heap: malloc 3: %lx\n", (long unsigned int) buf3); 
    recur(3); 
    return 0; 
} 

Выход этой программы выходит быть:Статическое распределение памяти в C

_main @ 4005c2 
_recur @ 40057d 
main call (i):[email protected] 7fff26397694 
_static foo: 601050 
_static stuff: 601048 
Heap: malloc 1: 1862010 
Heap: malloc 2: 1862080 
Heap: malloc 3: 18620f0 
recur call (i)3: [email protected] 7fff2639766c 
recur call (i)2: [email protected] 7fff2639763c 
recur call (i)1: [email protected] 7fff2639760c 
recur call (i)0: [email protected] 7fff263975dc 

Может кто-нибудь, пожалуйста, объясните следующее?

  • Почему адреса имеют разные байты, например. main, recur & static_varibale адреса составляют 6 * 4 = 24 байта, куча 7 * 4 = 28 байт, стек - 12 * 4 = 48 байтовый адрес.
  • Хотя я выделение 100 байт на каждую таНос разницы между таНосом 1 и таНосом 2 адресов 0x70 = 112 байт
  • Почему существует разница 0x601050 - 0x601048 = 8 между адресом обув и прочее, хотя оба они int и int занимает всего 4 байта?
+0

выравнивание, возможно ???? –

+0

Примечание: с именами функций, как и со статически распределенными массивами, нет необходимости использовать '&' для получения адреса (например, 'main' и' & main' обязательно идентичные значения). –

+0

Кроме того, фрейм стека для «recur» имеет значение 0x30 = 48 байт. Является ли это значение фиксированным или зависит от функции?Если его функция зависит, то функция recur имеет только две переменные int, объявленные «i» и «j», что делает только 2 * 4 = 8 байтов, тогда почему 48? – Utkarsh

ответ

2
  • Каждая часть программы (код, данные, стек ...) живет в различных разделах. Эти разделы отображаются в области памяти ОС, поэтому ответ заключается в том, что разница, которую вы видите, зависит от ОС. В вашем случае стек оказывается сопоставленным в более высокой области, но все адреса все еще 64-разрядные (адресное пространство может быть меньше, например, 48 бит).
  • Гарантировано, что malloc() поможет вам найти подходящий. В 64-битной среде он обычно находится на границе 16 байтов, поэтому 100 байтов, которые вы выделяете, будут округлены до 112 (7 * 16) для следующего выделения. Кроме того, malloc() необходимо отслеживать выделение с дополнительными данными, поэтому используемое пространство всегда будет больше, чем сумма malloc'ed.
  • Основное различие между stuff и foo является то, что один инициализируется, а другая не является, таким образом, stuff будет размещена в разделе .data и foo будет размещен в разделе .bss (нулевой инициализируются раздел). Это означает, что две переменные вряд ли будут рядом друг с другом. В вашем случае они близки, потому что больше ничего нет.
+0

Кроме того, фрейм стека для «recur» имеет значение 0x30 = 48 байт. Является ли это значение фиксированным или зависит от функции? Если его функция зависит, то функция recur имеет только две переменные int, объявленные «i» и «j», что делает только 2 * 4 = 8 байтов, тогда почему 48? – Utkarsh

+0

@UtkarshGupta Стек, используемый функцией, зависит от многих факторов. Вы можете иметь локальные переменные, хранящиеся в стеке, регистры CPU, пролитые (сохраненные) в стеке, но также пространство стека, зарезервированное для вызовов функций. Кроме того, для согласования вызова x64 требуется выровнять стек с выравниванием по 16 байт для вызовов функций. И есть указатель обратного адреса, нажатый на стек, для неизбежных 8 бонусных байтов. – ElderBug

+0

В чем разница между терминами сегмента и раздела? – Utkarsh

3

Прежде всего, ясно, что адреса являются адресами виртуальной памяти вашего пространства памяти процесса. Тем не менее, расположение в пространстве памяти процесса является более или менее, как это для 32-битной среды:

0 +----------------------------------------+ 
    |    .text (code)    | 
    +----------------------------------------+ 
    | .data (initialized static variables) | 
    +----------------------------------------+ 
    | .bss (uninitialized static variables) | 
    +----------------------------------------+ <- Heap start, grows upwards 
    |     heap     | 
    +----------------------------------------+ 
    |     stack     | 
3GB +----------------------------------------+ <- Stack start, grows downwards 
    |    kernel code    | 
4GB +----------------------------------------+ 
  • Статических переменных адреса не являются более коротких размерами, все адреса 32-разрядные адреса, это только printf() -срезающих ведущие нули (посмотрите на диаграмму выше, статические переменные имеют низкие адреса).

  • malloc() обычно размещает данные бухгалтерии в дополнение к выделенному самому буфере. Это зависит от реализации.

  • «int занимает всего 4 байта», что зависит от вашей системы. Кроме того, компилятор мог добавить добавку для выравнивания фреймов стека.

Смежные вопросы