выделение памяти в стеке и куче

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

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

например,

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

6 ответов


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

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

int i;

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

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

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

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


надеюсь, следующее полезно:

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));
}

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

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

надеюсь, что это помогает.


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

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

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


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

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

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


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

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


ответ г-на Эберле на 100% правильный, но так как Google показывает это как первый ответ при поиске malloc heap or stack, Я должен добавить, что malloc() выделяет данные в куче "большую часть" времени. Если выделенные данные были больше MMAP_THRESHOLD который обычно 128kb на 32-разрядных системах,malloc() будет не используйте кучу и вместо этого выделяет данные в Анонимный Сегмент Памяти расположенный обычно под стек растет в сторону низких память.

это тот же регион, в котором расположены динамически загружаемые библиотеки (libc.so, etc.). Вот соответствующий отрывок из 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).

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