Я хотел бы знать, в чем разница между распределением статической памяти и распределением динамической памяти?
Не могли бы вы объяснить это с помощью любого примера?
Я хотел бы знать, в чем разница между распределением статической памяти и распределением динамической памяти?
Не могли бы вы объяснить это с помощью любого примера?
Существует три типа размещения - статические, автоматические и динамические.
Статическое размещение означает, что память для ваших переменных выделяется при запуске программы. Размер фиксируется при создании программы. Он применяется к глобальным переменным, переменным области видимости файла и переменным, соответствующим 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 */
Несколько странно говорить, что статическая память выделяется во время компиляции, особенно если мы начинаем считать, что компиляционная машина и хост-машина могут не совпадать или даже не иметь одинаковую архитектуру.
Может быть лучше подумать, что распределение статической памяти обрабатывается компилятором, а не выделяется во время компиляции.
Например, компилятор может создать большой раздел data
в скомпилированном двоичном файле, и когда программа загружается в память, адрес в сегменте data
программы будет использоваться в качестве местоположения выделенной памяти. Это имеет явный недостаток - делать скомпилированный двоичный файл очень большим, если используется много статической памяти. Можно написать двоичный файл размером в несколько гигабайт, сгенерированный из менее чем полдюжины строк кода. Другим вариантом для компилятора является внедрение кода инициализации, который будет распределять память каким-либо другим способом до выполнения программы. Этот код будет отличаться в зависимости от целевой платформы и ОС. На практике современные компиляторы используют эвристику, чтобы решить, какой из этих параметров использовать. Вы можете попробовать это самостоятельно, написав небольшую C-программу, которая выделяет большой статический массив из элементов 10k, 1m, 10m, 100m, 1G или 10G. Для многих компиляторов размер двоичного файла будет расти линейно с размером массива, и после определенной точки он снова сократится, поскольку компилятор использует другую стратегию размещения.
Последний класс памяти является переменными 'register'. Как и ожидалось, переменные регистра должны быть размещены в регистре процессора, но решение фактически остается за компилятором. Вы не можете превратить переменную регистра в ссылку, используя address-of.
register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
Большинство современных компиляторов умнее, чем вы, выбираете, какие переменные следует помещать в регистры :)
Распределение статической памяти:
Динамическое распределение памяти:
Распределение статической памяти: Компилятор выделяет требуемое пространство памяти для объявленной переменной. Используя адрес оператора, зарезервированный адрес получен, и этот адрес может быть назначен переменной указателя. Поскольку у большей части объявленной переменной есть статическая память, этот способ присвоения значения указателя переменной указателя известен как распределение статической памяти. память назначается во время компиляции.
Динамическое распределение памяти:. Он использует функции, такие как malloc() или calloc(), чтобы динамически получать память. Если эти функции используются для динамического получения памяти, а значения, возвращаемые этими функциями, переменные указателя, такие назначения называются динамическим распределением памяти. memory определяется во время выполнения.
Разница между РАСПРЕДЕЛЕНИЕ СТАТИЧЕСКОЙ ПАМЯТИ и РАСПРЕДЕЛЕНИЕ ДИНАМИЧЕСКОЙ ПАМЯТИ
Память выделяется до запуска программы
(Во время компиляции).
Память выделяется во время выполнения программы.
Во время выполнения не выполняются действия по распределению памяти или освобождению.
Привязывание памяти установлено и уничтожается во время выполнения.
Переменные остаются постоянно выделенными.
Выделено только при активном программном блоке.
Реализовано с использованием стеков и кучек.
Реализовано с использованием сегментов данных.
Указатель необходим для доступа к переменным.
Нет необходимости динамически выделяемых указателей.
Более быстрое выполнение, чем динамическое.
Более медленное выполнение, чем статическое.
Требуется дополнительная память. Требуется меньше места памяти.
Распределение статической памяти выделяет память перед выполнением pf-программы во время компиляции. Динамическое выделение памяти - это выделенная память во время выполнения программы во время выполнения.
Размещение статической памяти. Выделенная память будет в стеке.
int a[10];
Динамическое распределение памяти. Выделенная память будет в куче.
int *a = malloc(sizeof(int) * 10);
а последний должен быть свободен d, так как в C отсутствует сборщик мусора (GC).
free(a);
Статическая память: статические запоминающие устройства представляют собой полупроводниковые запоминающие устройства, в которых сохраненные данные будут оставаться навсегда сохраненными до тех пор, пока будет подана мощность без необходимости периодической перезаписи или обновления данных в памяти. Основным элементом этого хранилища является флип-флоп или ворота. SRAM, перфокарт и лента являются примерами статической памяти.
Статическая память: Статические запоминающие устройства представляют собой полупроводниковые запоминающие устройства, в которых сохраненные данные будут оставаться навсегда сохраненными до тех пор, пока питание будет применено без необходимости периодической перезаписи или обновления данных в памяти. Основным элементом этого хранилища является флип-флоп или ворота. SRAM, перфокарт и лента являются примерами статической памяти.
Динамическая память:. Динамические запоминающие устройства представляют собой полупроводниковые запоминающие устройства, в которых сохраненные данные не будут сохраняться навсегда, даже при подаче питания, если данные не будут периодически перезаписаны в память. Данные хранятся в качестве заряда на конденсаторах. Заряд на конденсаторе должен периодически обновляться, чтобы предотвратить его утечку. DRAM и устройство с зарядовой связью (CCD) являются примером динамической памяти.