Динамічний розподіл пам'яті в C
Динамічний розподіл пам'яті в C — це спосіб ручного керування пам'ятю в мові програмування C за допомогою функцій стандартної бібліотеки, а саме malloc, realloc, calloc, aligned_alloc та free. [1] [2]
Попри те, що ці функції наявні в C++, автори закликають використовувати більш безпечні оператори new та delete. [3] Хоча існують винятки, де їх використання не рекомендується. Серед них, чутливі до продуктивності ділянки коду або реалізація прибиральника сміття.
Існує безліч механізмів перерозподілу пам'яті, що базуються на функції malloc. Вони можуть відрізнятися за швидкістю виконання чи споживанню пам'яті.
Функції динамічного розподілу пам’яті знаходяться у заголовку stdlib.h
( заголовок cstdlib
в C++).
функція | опис |
---|---|
malloc
|
виділяє вказану кількість байтів |
aligned_alloc
|
виділяє вказану кількість байтів із вказаним вирівнюванням |
realloc
|
збільшує або зменшує розмір зазначеного блоку пам'яті, переміщуючи його за необхідності |
calloc
|
виділяє вказану кількість байтів та заповнює її нулями |
free
|
звільняє вказаний блок пам'яті назад до системи |
malloc()
приймає один аргумент (обсяг пам’яті для виділення в байтах), тоді якcalloc()
приймає два аргументи — кількість елементів і розмір кожного елемента.malloc()
виділяє лише пам’ять, тоді якcalloc()
виділяє та заповнює данну область пам'яті нулями. [4]
Створення масиву в С з десяти цілих чисел є доволі простим:
int array[10];
Але розмір масиву визначається під час компіляції. Якщо потрібно виділити його динамічно та без використання масиву змінної довжини, який присутній не в всіх реалізаціях C11, можна використати такий код:
int *array = malloc(10 * sizeof(int));
Він обчислює кількість байтів, які десять цілих чисел займають у пам’яті, потім виділяє їх через функцію malloc
. Адреса виділеного блоку пам'яті зберігається у змінній array
(завдяки синтаксису C, вказівники та масиви в деяких ситуаціях можуть використовуватись рівнозначно).
Оскільки функція malloc
не гарантує виділення пам'яті, вона може повернути нульовий вказівник у разі помилки. Перевіряти це в програмуванні вважається хорошою практикою:
int *array = malloc(10 * sizeof(int));
if (array == NULL) {
fprintf(stderr, "malloc failed\n");
return -1;
}
Після того, як динамічний масив більше не потрібен, потрібно викликати функцію free
, щоб звільнити пам'ять, яку він займає:
free(array);
Пам'ять, що виділена malloc
не є ініціалізована за замовчуванням та може містити залишки роботи попередніх програм. Тобто, елементи масиву виділеного за допомогою malloс
є неініціалізованими змінними. Функція calloc
повертає пам'ять, що очищується за замовчуванням.
int *array = calloc(10, sizeof(int));
За допомогою функції realloc
ми можемо змінити розмір пам’яті, якап вже була виділеною. Наприклад, якщо у нас є вказівник, що вказує на масив розміру і ми хочемо змінити його розмір на , ми можемо скористатися realloc
.
int *arr = malloc(2 * sizeof(int));
arr[0] = 1;
arr[1] = 2;
arr = realloc(arr, 3 * sizeof(int));
arr[2] = 3;
Варто зазначити, що realloc
може повернути вказівник на нову адресу. Тобто, якщо блок пам'яті, що належить вказівнику, не може бути розширеним, realloc
виділить новий блок пам'яті та зкопіює туди старі дані. Тоді попередній вказівник буде більше не дійсним.
- ↑ Summit, Steve. Chapter 11: Memory Allocation. C Programming Notes. Процитовано 11 липня 2020.
- ↑ aligned_alloc(3) - Linux man page.
- ↑ Stroustrup, Bjarne (2008). Programming: Principles and Practice Using C++. Addison Wesley. с. 1009. ISBN 978-0-321-54372-1.
- ↑ Linux Programmer's Manual – Library Functions –