если размер стека составляет 1 МБ, означает ли это, что я могу получить только менее 1000000/8 указателей для распределения целых чисел в куче? (учитывая свободный стек в 1 МБ) да, я знаю, что вы, возможно, не захотите создавать так много отдельных целых чисел в куче, но все же это ограничивает количество объектов, которые вы можете динамически выделить.
разве это не делает целые числа в стеке лучшим выбором? (целые числа здесь имеют размер 4 байта)
редактировать: я получаю комментарии о том, что такое использование указателей, это не то, о чем я спрашиваю, я имел в виду, что при ограниченном размере стека не существует ли ограниченного «количества», а не «размера» вещей, к которым вы можете получить доступ/сделать в куче?
А если вы имеете в виду стек, то вызовы компилятора и функций, ведущие к функции main
, будут хранить другие данные в стеке, поэтому доступно менее одного МиБ. При этом то, что останется, можно использовать для заполнения локальными переменными, а если это указатели, то в 64-битной системе каждый указатель будет использовать восемь байт. Так что ваш расчет примерно верен. Однако, куда именно указывают все эти указатели, совершенно не имеет значения. Они могут указывать на кучу, стек или другие данные (например, глобальные переменные) и т. д.
да, спасибо, что указали на опечатку, и да, я знаю о других вещах, занимающих стек, поэтому я сказал (учитывая свободный стек в 1 МБ). да, не имеет значения, на что они указывают, я просто хотел сказать, что могу динамически создавать только ограниченное количество «вещей» в куче, создавая указатели в стеке
Когда вы выделяете массив, у вас есть 1 указатель на массив. Не отдельный указатель на каждый отдельный элемент.
Также обратите внимание, что если вы заполните стек локальными переменными, то вы не сможете вызывать никакие функции, в том числе malloc
для создания места в куче.
@drescherjm, да, в этом случае я могу создавать только ограниченное количество «массивов», причем ограничением является размер стека
К вашему сведению, указатели не ограничиваются элементами в куче. Во встраиваемых системах мы используем указатели для доступа к аппаратным устройствам, например к драйверу USB.
Вы можете выделить объект в куче, и этот объект может иметь столько динамически выделенных объектов, сколько может поместиться в пространстве виртуальной памяти вашего процесса, поэтому ограничение стека в этом примере не применяется.
По умолчанию стек может составлять 1 МБ. Ничто не мешает вам изменить настройки по умолчанию для программы, которой требуется больше места. Почему размер стековой памяти настолько ограничен?
К вашему сведению, существуют компиляторы и операционные системы, которые организуют память так, что стек находится на одном конце, а куча — на другом. Они «прирастают» друг к другу. Таким образом, вы можете иметь огромный стек, рискуя получить минимальную кучу.
Возможно, путаница в том, что ОП (правильно) считает, что результат каждого динамического распределения должен где-то храниться; эти результаты не связаны между собой и не могут быть упрощены до арифметики указателей. Затем, если вы хотите сохранить результаты в стеке, вам действительно придется уместиться в доступное пространство стека. Конечно, вы можете сохранить результаты где-нибудь еще.
В стеке может быть один указатель, указывающий на диапазон указателей в куче. Каждый из этих указателей, в свою очередь, может указывать на разные места в куче. Так что практически нет.
Стек и куча не имеют ничего общего друг с другом. Ограниченный размер стека просто означает, что у вас есть ограниченное количество места для хранения таких вещей, как локальные переменные и параметры вызова функций. Это не имеет ничего общего с тем, сколько места вы можете динамически выделить в куче.
Например:
int *ptr1 = (int*) malloc(sizeof(int) * N);
int *ptr2 = (int*) malloc(sizeof(int) * M);
ptr1
и ptr2
— это локальные переменные, созданные в стеке, но они указывают на динамическую память, выделенную в куче. Размер стека не влияет на то, сколько места находится в куче:
Stack Heap
+-----------+ +-------------+
| | | |
| +------+ | | +--------+ |
| | ptr1 | -|-----------|->| 12345 | |
| +------+ | | +--------+ |
| +------+ | | | 67890 | |
| | ptr2 | -|-----+ | +--------+ |
| +------+ | | | | ... | |
| | | | +--------+ |
+-----------+ | | |
| | +--------+ |
+-----|->| 12345 | |
| +--------+ |
| | 67890 | |
| +--------+ |
| | ... | |
| +--------+ |
| |
+-------------+
Кажется, вы предполагаете, что наличие небольшого стека означает, что в куче может быть только X указателей. Это неправда. Например, указатель можно переместить из стека в элемент объекта, существующий в куче:
Stack Heap
+-----------+ +-------------+
| | | |
| +------+ | | +--------+ |
| | ptr1 | -|-----------|->| member | -----+
| +------+ | | +--------+ | |
| +------+ | | | |
| | ptr2 | -|-----+ | +--------+ | |
| +------+ | | | | 12345 | <----+
| | | | +--------+ |
+-----------+ | | | 67890 | |
| | +--------+ |
| | | ... | |
| | +--------+ |
| | |
| | +--------+ |
+-----|->| 12345 | |
| +--------+ |
| | 67890 | |
| +--------+ |
| | ... | |
| +--------+ |
| |
+-------------+
Я считаю, что путаница вращается вокруг предположения, что каждое распределение кучи выделяет 1 объект и имеет 1 указатель в стеке. Поэтому устанавливается верхнее ограничение на общее количество выделений. Этот ответ можно было бы дополнить, пояснив, что оба эти предположения ложны.
Под «если размер кучи составляет 1 МБ», я полагаю, вы имели в виду «если размер стека составляет 1 МБ»? Пожалуйста, отредактируйте свой вопрос, чтобы исправить возможные опечатки и другие проблемы, которые могут возникнуть.