Какие данные хранятся в стеке (stack) в iOS/macOS?

Ответ

Стек (stack) — это область памяти для хранения локальных и временных данных с чётким LIFO (Last-In, First-Out) порядком жизни, привязанных к текущему контексту выполнения (функции, методу).

Что хранится в стеке:

  • Локальные переменные типов-значений (Value Types): Int, Double, Bool, struct, enum и т.д.
  • Ссылки (указатели) на объекты в куче. Сами объекты — в куче, но переменные, которые на них ссылаются, — в стеке.
  • Аргументы, передаваемые в функции.
  • Адреса возврата из функций (куда передать управление после завершения).
  • Служебная информация о вызове функций (фреймы стека).

Ключевые особенности стека:

  • Очень быстрый: Выделение и освобождение памяти — это просто движение указателя стека.
  • Автоматическое управление: Память освобождается сразу при выходе из области видимости (scope).
  • Ограниченный размер: Размер стека фиксирован и относительно мал (несколько МБ). Переполнение стека — частая причина крашей при глубокой рекурсии.
  • Потокобезопасность: У каждого потока свой собственный стек.

Пример:

func calculateSum(a: Int, b: Int) -> Int { // `a` и `b` размещаются в стеке
    let result = a + b // Локальная переменная `result` (Int) размещается в стеке
    return result
} // При выходе из функции память для `a`, `b`, `result` автоматически освобождается

let x = 5 // `x` (Int) в стеке главного потока
let y = 10 // `y` (Int) в стеке
let sum = calculateSum(a: x, b: y) // При вызове в стек помещаются копии x и y

Ответ 18+ 🔞

А, слушай, про стек, да? Ну это ж классика, блядь! Представь себе стопку тарелок, ёпта. Ту, которую последней поставил — ту первой и возьмёшь. LIFO, блядь, Last-In, First-Out, как мой последний глоток пива из холодильника — он же первый на выходе, в рот меня чих-пых!

Что там внутри валяется, в этой стопке-то?

  • Все эти твои циферки да буковки: Int, Double, Bool, всякие struct-ы и enum-ы — они прямо там, в стопке, живут, как родные.
  • Ссылочки-указатели на объекты в куче. Сам объект — там, в бардаке (в куче), а бумажка с его адресом — аккуратненько в стопке лежит.
  • Аргументы, которые ты в функцию пихаешь.
  • Адреса возврата — чтобы система не заблудилась и знала, куда топать после того, как функция отработает.
  • И всякая служебная хуйня про вызовы функций, фреймы стека там...

А главные фишки стека какие?

  • Скорость — пиздец! Выделить память? Просто двинул указатель. Освободить? Двинул обратно. Быстрее только деньги с карты списывать.
  • Уборка автоматом. Вышел из функции (из области видимости) — всё, что там было, нахуй стёрлось. Никакого мусора за собой не тащишь.
  • Размер — не ахти. Стек-то маленький, несколько мегабайт. Если начнёшь глубоко рекурсию гнать — переполнение стека тебе обеспечено, и приложение накроется медным тазом, блядь.
  • Каждый поток — со своим шкафчиком. У каждого потока свой личный стек, чтобы не путались и не дрались.

Ну и пример, чтобы совсем доходило:

func calculateSum(a: Int, b: Int) -> Int { // `a` и `b` — уже в стеке легли
    let result = a + b // Локальная `result` (тоже Int) — тоже в стеке
    return result
} // Всё, вышли из функции — память подчистили, красота!

let x = 5 // `x` в стеке главного потока
let y = 10 // `y` тут же
let sum = calculateSum(a: x, b: y) // Вызвали функцию — скопировали x и y в стек для работы

Вот и вся магия, ёбушки-воробушки. Быстро, чисто, автоматически, но места мало. Как в коммуналке, блядь.