выделение памяти в стеке и куче
Это может показаться очень основным вопросом, но он был в моей голове так:
когда мы выделяем локальную переменную, она переходит в стек. Аналогично динамическое распределение приводит к тому, что переменная переходит в кучу. Теперь мой вопрос: эта переменная действительно лежит на стеке или куче, или мы будем просто ссылкой в стеке и куче.
например,
предположим, я объявляю переменную 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>
чтобы показать соответствующую память сегмент.