Jochen Arndt
Существуют различные виды складских помещений:
- Текст: содержит исполняемый код (названный здесь для полноты картины)
- Инициализированные данные: глобальные и статические переменные
- Неинициализированные данные: глобальные и статические переменные (инициализируются до нуля при запуске приложения)
- Стек: локальные переменные
- Куча: выделенное хранилище с использованием
new()
или malloc()
Память для первых двух типов является частью самого исполняемого файла и выделяется операционной системой при загрузке приложения в память.
Память для неинициализированных глобальных данных также выделяется операционной системой и инициализируется до нуля.
Память стека выделяется операционной системой при запуске потока. Для основного потока размер определяется из исполняемого файла. Другие потоки, созданные во время выполнения, будут использовать тот же размер, что и значение по умолчанию, но другой размер может быть передан в качестве параметра функции создания потока.
Каждый раз, когда создается локальная переменная, ей присваивается адрес объекта.
указатель стека и это уменьшается на размер переменной (стеки используют память в направлении сверху вниз). Как только указатель стека достигает дна, происходит переполнение стека и приложение завершает работу, поскольку память стека не может быть изменена во время выполнения.
Компилятор может также решить хранить локальные переменные в регистрах процессора вместо стека. Это также может быть предложено с помощью
register
ключевое слово.
Кучная память выделяется кусками во время выполнения. Это делается с помощью кода, вставляемого компилятором в каждое приложение (вызывается
менеджер кучиЕсли запрос на память не может быть выполнен из текущей памяти кучи, диспетчер кучи запросит у операционной системы больший блок памяти.
Как правило, нет никакой разницы между выделением памяти или назначением базовых и сложных типов (кроме того, компилятор может хранить базовые типы в регистрах, а не в стеке).
Примеры:
// Initialised global data
int global1 = 1;
static int global2 = 2;
// Uninitialised global data (will be set to zero)
int global1U;
static int* globalPtr;
void some_func()
{
// Initialised static data
static int localS1 = 1;
// Uninitialised static data
static int localS2;
// Local variables on the stack
// The compiler might store some of them in CPU registers
int local1;
int local2 = 2;
int localArr[10];
SomeObj obj;
// Local variable stored in CPU register
// Deprecated with C++17 and the compiler may ignore it (use the stack instead)
register r = 0;
// Heap memory where the pointer is stored as local variable
int *localPtr = new int[10];
SomeObj *objPtr = new SomeObj();
// Heap memory where the pointer is stored in a global variable
globalPtr = new int[10];
}