Я хотів би знати, в чому різниця між статичним виділенням пам'яті та динамічним виділенням пам'яті?
Не могли б ви пояснити це на будь-якому прикладі?
Я хотів би знати, в чому різниця між статичним виділенням пам'яті та динамічним виділенням пам'яті?
Не могли б ви пояснити це на будь-якому прикладі?
Відповіді:
Існує три типи розподілу - статичний, автоматичний та динамічний.
Статичний розподіл означає, що пам'ять для ваших змінних виділяється під час запуску програми. Розмір фіксується під час створення програми. Це застосовується до глобальних змінних, змінних області файлу та змінних, кваліфікованих за допомогою 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 */
Дещо заплутано стверджувати, що статична пам’ять виділяється під час компіляції, особливо якщо ми починаємо вважати, що машина компіляції та хост-машина можуть бути не однаковими або навіть не мати однакової архітектури.
Можливо, краще подумати, що виділення статичної пам'яті обробляється компілятором, а не виділяється під час компіляції .
Наприклад, компілятор може створити великий data
розділ у скомпільованому двійковому файлі, і коли програма завантажується в пам'ять, адреса всерединіdata
сегмент програми буде використовуватися як місце розташування виділеної пам'яті. Це має помітний недолік - зробити скомпільований двійковий файл дуже великим, якщо використовується велика кількість статичної пам'яті. Можна написати багатогігабайтний двійковий файл, згенерований менш ніж з півдюжини рядків коду. Інший варіант - компілятор ввести код ініціалізації, який виділить пам’ять якимось іншим способом перед запуском програми. Цей код буде залежати від цільової платформи та ОС. На практиці сучасні компілятори використовують евристику, щоб вирішити, який із цих варіантів використовувати. Ви можете спробувати це самостійно, написавши невелику програму на С, яка виділяє великий статичний масив із елементів 10k, 1m, 10m, 100m, 1G або 10G. Для багатьох компіляторів бінарний розмір буде продовжувати зростати лінійно із розміром масиву, і минувши певну точку,
Останнім класом пам’яті є змінні 'register'. Як і слід було очікувати, змінні реєстру повинні бути розподілені в реєстрі ЦП, але рішення фактично залишається за компілятором. Ви не можете перетворити змінну реєстру на посилання, використовуючи адресу-of.
register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
Більшість сучасних компіляторів розумніші за вас, вибираючи, які змінні слід вносити в регістри :)
int * a = malloc(sizeof(*a));
Замість цього я пропоную уникати повторення типу a
. Це робить речі набагато простішими, якщо ніколи, типом a
змін.
Розподіл статичної пам'яті: Компілятор виділяє необхідний простір пам'яті для оголошеної змінної. Використовуючи адресу оператора, отримується зарезервована адреса, і ця адреса може бути присвоєна змінній покажчика. Оскільки більшість оголошеної змінної має статичну пам'ять, це спосіб присвоєння значення покажчика змінній покажчика відомий як статичне виділення пам'яті. пам'ять призначається під час компіляції.
Динамічне розподіл пам'яті: Він використовує такі функції, як malloc () або calloc (), щоб динамічно отримувати пам'ять. Якщо ці функції використовуються для динамічного отримання пам'яті, а значення, що повертаються цими функціями, відносяться до змінних покажчика, такі призначення відомі як динамічна пам'ять allocation.memory призначається під час виконання.
Виділення статичної пам'яті:
Динамічне розподіл пам'яті:
Різниця між СТАТИЧНИМ РОЗПОДІЛОМ ПАМ’ЯТІ І ДИНАМІЧНИМ РОЗПОДІЛОМ ПАМ’ЯТІ
Пам'ять виділяється до початку виконання програми (Під час компіляції).
Пам'ять виділяється під час виконання програми.
Під час виконання не виконуються дії з виділення або звільнення пам'яті.
Прив’язки пам’яті встановлюються та руйнуються під час Страти.
Змінні залишаються постійно розподіленими.
Виділяється лише тоді, коли активний програмний блок.
Реалізовано за допомогою стеків і куп.
Реалізовано за допомогою сегментів даних.
Для доступу до змінних потрібен вказівник.
Немає необхідності в динамічно розподілених покажчиках.
Швидше виконання, ніж динамічне.
Повільніше виконання, ніж статичне.
Потрібно більше місця в пам'яті.
Потрібно менше місця в пам'яті.
Виділення статичної пам'яті виділяється пам’яттю перед виконанням програми pf під час компіляції. Динамічне виділення пам'яті - це виділена пам’ять під час виконання програми під час виконання.