распределение памяти в стеке и куче - PullRequest
18 голосов
/ 21 июля 2011

Это может показаться очень простым вопросом, но он был у меня в голове так:

Когда мы выделяем локальную переменную, она помещается в стек.Точно так же динамическое размещение заставляет переменную идти в кучу.Теперь мой вопрос заключается в том, находится ли эта переменная на самом деле в стеке или куче, или мы будем просто ссылкой в ​​стеке и куче.

Например,

Предположим, я объявил переменную int i,Теперь это i размещено в стеке.Итак, когда я печатаю адрес i, это будет одно из мест в стеке?Тот же вопрос и для кучи.

Ответы [ 6 ]

44 голосов
/ 21 июля 2011

Я не совсем уверен, что вы спрашиваете, но я постараюсь ответить как можно лучше.

Следующее объявляет переменную i в стеке:

int i;

Когда я запрашиваю адрес, используя &i, я получаю фактическое местоположение в стеке.

Когда я выделяю что-то динамически, используя malloc, на самом деле TWO фрагменты данных, которые хранятся.Динамическая память выделяется в куче, а сам указатель выделяется в стеке.Итак, в этом коде:

int* j = malloc(sizeof(int));

Это место в куче для целого числа.Он также выделяет место в стеке для указателя (j).Значение переменной j устанавливается на адрес, возвращаемый malloc.

10 голосов
/ 21 июля 2011

Надеемся, что полезно следующее:

void foo()
{
    // an integer stored on the stack
    int a_stack_integer; 

    // a pointer to integer data, the pointer itself is stored on the stack
    int *a_stack_pointer; 

    // make a_stack_pointer "point" to integer data that's allocated on the heap
    a_stack_pointer = (int*)malloc(10 * sizeof(int));
}

В случае переменных стека сама переменная (фактические данные) сохраняется в стеке.

В случае кучивыделенная память, базовые данные всегда хранятся в куче.Указатель на эту память / данные может храниться локально в стеке.

Надеюсь, это поможет.

5 голосов
/ 21 июля 2011

Сама переменная-указатель будет находиться в стеке. Память, на которую указывает указатель, будет находиться в куче.

int *i = malloc(sizeof(int));

i будет находиться в стеке, фактическая память, на которую я указываю *i, будет в куче.

2 голосов
/ 03 июня 2013

Я согласен с Крисом. Просто еще один способ объяснить это. Рассмотрим следующий код:

int* j = malloc(sizeof(int));
free(j);

Даже после использования free (j), который должен освободить память из кучи, указатель все еще существует, и нам нужно явно сделать его NULL. Это определенно говорит о том, что есть также стек-аналог указателя, в противном случае он должен был бы отсутствовать после свободной команды. Эта переменная стека указывает на адрес в куче, где память была динамически выделена с помощью malloc.

0 голосов
/ 25 августа 2018

г. Ответ Эберле на 100% правильный, но так как Google показывает его в качестве первого ответа при поиске malloc heap or stack, я должен добавить, что malloc() выделяет данные в куче «большую часть времени». Если выделенные данные были больше чем MMAP_THRESHOLD, что обычно составляет 32 КБ в 32-разрядных системах, malloc() будет не использовать кучу и вместо этого распределяет данные в Сегмент анонимной памяти , расположенный обычно ниже стека и растущий в направлении нехватки памяти.

Это та же область, в которой расположены динамически загружаемые библиотеки (libc.so и т. Д.). Вот соответствующий отрывок из man malloc:

Обычно malloc () выделяет память из кучи и настраивает размер кучи по мере необходимости, используя sbrk (2). При размещении блоков памяти больше, чем MMAP_THRESHOLD байт, Реализация glibc malloc () выделяет память как частное анонимное отображение, используя mmap (2). MMAP_THRESHOLD по умолчанию составляет 128 кБ, но настраивается с помощью mallopt (3). До Распределения Linux 4.7, выполняемые с использованием mmap (2), не зависели от ограничения ресурса RLIMIT_DATA; начиная с Linux 4.7, это ограничение также применяется для распределений, выполняемых с помощью mmap (2).

В качестве практического примера не стесняйтесь проверять следующий пост . Он в основном выделяет 300 Кбайт с malloc(), а затем запускает pmap <PID>, чтобы показать соответствующий сегмент памяти.

0 голосов
/ 21 июля 2011
Стек

или куча не являются отдельной памятью, они представляют собой сегменты памяти, которые исполняемая программа выделяет системой, просто различные способы организации данных в памяти.

Итак, когда вы получаете & i, это адрес памяти, простой как этот.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...