Масиви довільної довжини і динамічне виділення пам'яті на стеку
У С90 немає можливості створити масив довільної довжини. Розмір масиву повинен бути відомий на момент компіляції
У стандарті С99 з'явилася можливість створювати масиви, розмір яких не відомий на момент компіляції. Наприклад, можна передати функції розмір масиву і створити тимчасовий масив
Масиви довільної довжини можна форматувати при створенні. Наприклад, наступний код не скомпілюється
Зроблено це (мабуть) з міркувань безпеки. Якщо необхідно заповнити масив значеннями, то це можна зробити поелементно, або, наприклад, за допомогою функції memset.
Проте, VSE не підтримує це нововведення і не збирається надалі.
Яким чином можна динамічно створити масив довільного розміру на стеку? Очевидно, нам потрібна така функція, яка б дозволяла виділяти пам'ять на стеку. Ця функція називається alloca, або _alloca і визначена в бібліотеці malloc.h
(Тут і далі у нестандартних функцій йде префіксом підкреслення. У GNU версіях компіляторів його немає). Так як пам'ять виділяється на стеку, то немає необхідності її підчищати - після виходу з функції стек буде відновлений і локальні змінні «знищені». До того ж, виділення пам'яті відбувається дуже швидко (на кілька порядків швидше, ніж виділення на купі) і не призводить до фрагментації.
Але тут виникає та ж проблема, що і з масивами довільної довжини - якщо виділити занадто багато пам'яті, то відбудеться переповнення стека. Функція _alloca, на відміну від malloc, не повертає NULL, якщо не змогла виділити пам'ять, а створює структуроване виключення переповнення стека. Наприклад, викличте
Тому пропонують такий спосіб виділення
Не дуже-то красиво. Звільнення пам'яті відбувається тільки після виходу з функції, а не після виходу за межі видимості. Функція _alloca була в подальшому заборонена і замінена на функцію _malloca. Він відрізняється тим, що спочатку намагається виділити місце на стеку, а якщо не змогла цього зробити, то виділяє місце на купі, тобто, працює як malloc. Однак якщо пам'ять може бути виділена на купі, то її доведеться звільняти після себе. Для цього використовується функція _freea. Якщо пам'ять була виділена на стеку, то функція нічого не робить. Якщо пам'ять була виділена на купі, то _freea звільняє її як стандартна free. Це ціна за більш безпечне використання.
malloca в разі виділення пам'яті на купі поводиться як і malloc. Тобто, якщо пам'ять не вдалося виділити на купі, то буде повернуто NULL.
ЗАУВАЖЕННЯ: _malloca виділятиме пам'ять на стеку тільки в релізі. У налагоджувальної версії проекту пам'ять завжди виділяється на купі.
ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 [email protected] Stepan Sypachev students