Почему невозможно хранить все данные в стеке?

«Почему невозможно хранить все данные в стеке?» — вопрос из категории Управление памятью, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Стек — это высокоскоростная, но ограниченная область памяти, непригодная для хранения всех данных из-за фундаментальных проектных ограничений:

1. Ограниченный и фиксированный размер: Размер стека потока задается при его создании (порядка нескольких МБ) и не может динамически расширяться. Хранение больших массивов или структур приведет к переполнению стека (Stack Overflow).

2. Время жизни, привязанное к области видимости: Память в стеке автоматически освобождается при выходе из функции (области видимости). Невозможно создать объект в функции и вернуть ссылку на данные в стеке — они будут сразу невалидны.

3. Отсутствие динамичности: Размер и layout стека должны быть известны на этапе компиляции. Невозможно выделить память под объект, размер которого определяется во время выполнения.

Пример иллюстрации проблемы:

func riskyFunction() {
    // Попытка выделить большой массив.
    // На практике Swift для Array использует кучу, но если бы это был стек:
    var hugeArrayOnStack = Array<Int>(repeating: 0, count: 1_000_000) // ~8 MB.
    // Высокая вероятность переполнения стека типичного потока (например, 2 MB).
}

Роль кучи: Куча решает эти проблемы, позволяя динамически выделять блоки памяти произвольного размера с независимым временем жизни, управляемым через ссылки и ARC. За это приходится платить производительностью.