Разница между статическим распределением памяти и динамическим распределением памяти

Я хотел бы знать, в чем разница между статическим распределением памяти и динамическим распределением памяти?

Не могли бы вы объяснить это на каком-либо примере?

7 ответов

Решение

Существует три типа размещения - статическое, автоматическое и динамическое.

Статическое распределение означает, что память для ваших переменных выделяется при запуске программы. Размер фиксируется при создании программы. Это относится к глобальным переменным, переменным области файла и переменным, квалифицированным с static определены внутри функции.

Автоматическое распределение памяти происходит для (нестатических) переменных, определенных внутри функций, и обычно хранится в стеке (хотя стандарт C не требует использования стека). Вам не нужно резервировать дополнительную память, используя их, но, с другой стороны, вы также имеете ограниченный контроль над временем жизни этой памяти. Например: автоматические переменные в функции присутствуют только до ее завершения.

void func() {
    int i; /* `i` only exists during `func` */
}

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

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

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

free(mem);

Это стандартный вопрос интервью:

Динамическое распределение памяти

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

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

Память кучи сохраняется до free() называется. Другими словами, вы контролируете время жизни переменной.

Автоматическое распределение памяти

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

int a = 43;

Обратите внимание, что область действия не обязательно означает функцию. Области могут быть вложены в функцию, и переменная будет находиться в области видимости только внутри блока, в котором она была объявлена. Также обратите внимание, что место, где выделяется эта память, не указано. (В здравой системе это будет в стеке, или регистры для оптимизации)

Статическое распределение памяти

Распределяется во время компиляции, а время жизни переменной в статической памяти - это время жизни программы.

В C статическая память может быть выделена с помощью static ключевое слово. Область действия - только единица компиляции.

Вещи становятся более интересными, когда extern ключевое слово считается. Когда extern переменная определена, компилятор выделяет для нее память. Когда extern переменная объявлена, компилятор требует, чтобы переменная была определена в другом месте. Неспособность объявить / определить extern переменные вызовут проблемы со связыванием, а объявление / определение не удастся static переменные вызовут проблемы компиляции.

в области действия файла статическое ключевое слово является необязательным (вне функции):

int a = 32;

Но не в области действия функции (внутри функции):

static int a = 32;

Технически, extern а также static два отдельных класса переменных в C.

extern int a; /* Declaration */
int a; /* Definition */

Зарегистрировать память

Последний класс памяти является переменными 'register'. Как и ожидалось, переменные регистра должны быть размещены в регистре процессора, но решение фактически остается за компилятором. Вы не можете превратить переменную регистра в ссылку, используя address-of.

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

Большинство современных компиляторов умнее, чем вы, выбираете, какие переменные следует помещать в регистры:)

Рекомендации:

Примечания о статическом распределении памяти

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

Возможно, лучше подумать, что распределение статической памяти обрабатывается компилятором, а не выделяется во время компиляции. Например, компилятор может создать большой data раздел в скомпилированном двоичном файле, и когда программа загружается в память, адрес в data Сегмент программы будет использоваться как расположение выделенной памяти. Это имеет явный недостаток - делать скомпилированный двоичный файл очень большим, если используется много статической памяти. Можно написать двоичный файл размером в несколько гигабайт, сгенерированный из менее чем полдюжины строк кода. Другим вариантом для компилятора является внедрение кода инициализации, который будет распределять память каким-либо другим способом до выполнения программы. Этот код будет отличаться в зависимости от целевой платформы и ОС. На практике современные компиляторы используют эвристику, чтобы решить, какой из этих параметров использовать. Вы можете попробовать это самостоятельно, написав небольшую C-программу, которая выделяет большой статический массив из элементов 10k, 1m, 10m, 100m, 1G или 10G. Для многих компиляторов размер двоичного файла будет расти линейно с размером массива, и после определенной точки он снова сократится, поскольку компилятор использует другую стратегию распределения.

Распределение статической памяти: компилятор выделяет требуемое пространство памяти для объявленной переменной. Используя адрес оператора, зарезервированный адрес получается, и этот адрес может быть назначен переменной-указателю. Поскольку большая часть объявленной переменной имеет статическую память, это способ присвоения значения указателя переменной указателя известен как статическое выделение памяти. память назначается во время компиляции.

Динамическое выделение памяти: для динамического получения памяти используются такие функции, как malloc() или calloc(). Если эти функции используются для динамического получения памяти, а значения, возвращаемые этими функциями, присваиваются переменным-указателям, такие назначения называются динамической памятью. Выделение памяти происходит во время выполнения.

Динамическое выделение памяти - память выделяется во время выполнения в куче. Это используется, когда объем (размер) памяти является переменным и известен только во время выполнения. Динамическое размещение достигается с помощью определенных функций, таких как malloc(), calloc(), realloc(), свободных в C и "new", "delete" в C++.

Распределение статической памяти - память, выделенная во время компиляции в стеке или других сегментах данных. Это используется, когда объем (размер) памяти является статическим / постоянным и известен во время компиляции.

Статическое выделение памяти. Выделенная память будет в стеке.

int a[10];

Динамическое распределение памяти. Выделенная память будет в куче.

int *a = malloc(sizeof(int) * 10);

и последний должен быть свободен d, так как в C. нет сборщика мусора (GC)

free(a);

Разница между РАСПРЕДЕЛЕНИЕМ СТАТИЧЕСКОЙ ПАМЯТИ и РАСПРЕДЕЛЕНИЕМ ДИНАМИЧЕСКОЙ ПАМЯТИ

Память выделяется до начала выполнения программы (во время компиляции).
Память выделяется при выполнении программы.

Во время выполнения никакие действия по выделению памяти или освобождению не выполняются.
Привязки памяти устанавливаются и уничтожаются во время выполнения.

Переменные остаются постоянно выделенными.
Распределяется только при активном программном блоке.

Реализовано с использованием стеков и куч.
Реализовано с использованием сегментов данных.

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

Более быстрое выполнение, чем Динамическое.
Более медленное выполнение, чем статическое.

Требуется больше памяти.
Требуется меньше памяти.

Статическое выделение памяти выделяется памяти перед выполнением программы во время компиляции. Динамическое выделение памяти - это выделение памяти во время выполнения программы во время выполнения.

Другие вопросы по тегам