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

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

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

7 ответов


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

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

автоматическое выделение памяти происходит (не-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 переменные вызовут проблемы с компиляцией.

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

int a = 32;

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

static int a = 32;

технически extern и static являются двумя отдельными классами переменных в C.

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

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

последний класс памяти переменных регистра. Как и ожидалось, переменные регистра должны быть распределены на Регистр CPU, но решение фактически оставлено компилятору. Вы не можете превратить переменную регистра в ссылку с помощью 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 (), realloc (), free в C и "new", "delete" в C++.

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


статическое выделение памяти: компилятор выделяет необходимое пространство памяти для объявленного variable.By используя адрес оператора, получается зарезервированный адрес, который может быть присвоен переменной указателя.Поскольку большая часть объявленной переменной имеет статическую память, Этот способ назначения значения указателя переменной указателя известен как статическое выделение памяти. память назначается во время компиляции.

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


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

int a[10];

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

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

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

free(a);

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

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

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

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

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

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

быстрее, чем динамические.
Медленнее, чем статические.

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


статическое выделение памяти выделяется память перед выполнением программы pf во время компиляции. Динамический alocation память выделена память во время выполнения программы во время выполнения.