← Назад к вопросам

С какой версии iOS появился Side Table?

2.8 Senior🔥 82 комментариев
#Управление памятью

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Подробный ответ о Side Table в iOS

Side Table — это низкоуровневый механизм управления ссылками в Objective-C, который существует с самых первых версий iOS, так как является неотъемлемой частью рантайма Objective-C. Точнее, он появился в OpenStep (предшественнике Cocoa и Cocoa Touch) и, соответственно, в iPhone OS 1.0 (позже переименованной в iOS). Его реализация содержится в открытом исходном коде runtime, который Apple публикует на opensource.apple.com.

Что такое Side Table и для чего он нужен?

Side Table — это вспомогательная структура данных, которая хранит "дополнительные" биты информации об объекте, когда для них не хватает места в самом заголовке объекта (objc_object). Основное назначение в современном ARC (Automatic Reference Counting) — хранение счетчиков слабых ссылок (weak references) и дополнительных данных для управления памятью.

Когда у объекта много слабых ссылок или нужно хранить дополнительные флаги (например, состояние deallocating), в основном заголовке объекта не хватает битов. Тогда runtime создает ассоциированную SideTable для этого объекта.

Ключевая архитектура и код

Основные структуры, связанные с Side Table, выглядят так (упрощенно, на основе открытого кода objc4):

// Упрощенная структура SideTable из исходников objc4
struct SideTable {
    spinlock_t slock;           // Спин-лок для синхронизации
    RefcountMap refcnts;        // Хэш-таблица для дополнительных счетчиков ссылок
    weak_table_t weak_table;    // Таблица слабых ссылок — САМОЕ ВАЖНОЕ!
};

// Заголовок объекта, в котором есть биты для хранения счетчика ссылок
struct objc_object {
private:
    isa_t isa;
public:
    // ...
};

weak_table_t внутри SideTable — это сердце механизма слабых ссылок. Когда вы объявляете свойство weak:

@property (nonatomic, weak) id someObject;

Компилятор генерирует код, который регистрирует эту ссылку в weak_table соответствующей SideTable. Когда объект начинает деаллокацию, runtime проходит по всем записям в weak_table и обнуляет (nil-out) соответствующие указатели, что предотвращает обращение к освобожденной памяти.

Почему Side Table так важен?

  1. Безопасность слабых ссылок: Гарантирует, что weak-переменные автоматически становятся nil после деаллокации объекта.
  2. Эффективность памяти: Не каждый объект имеет свою SideTable. Она создается только при необходимости (например, когда появляется первая слабая ссылка). Это экономит память.
  3. Поддержка старого кода: Обеспечивает работу retain/release вручную (MRC) и автоматического подсчета ссылок (ARC) в одной среде.
  4. Хранение дополнительных состояний: Помимо слабых ссылок, может хранить "лишние" биты счетчика сильных ссылок, если объект удерживается огромное количество раз (что случается редко).

Эволюция и современное состояние

  • iOS 1-4 / macOS 10.0-10.6: Side Table уже существовала, но детали реализации (например, тип блокировки) могли меняться.
  • С появлением ARC (iOS 5 / macOS 10.7): Роль Side Table значительно возросла, так как управление слабыми ссылками стало полностью автоматическим и массовым.
  • 64-битная архитектура (ARM64, x86_64): В заголовке объекта (objc_object) появилось больше бит для хранения счетчика ссылок (extra_rc и has_sidetable_rc), что оптимизировало работу и уменьшило необходимость в обращении к Side Table для многих объектов.
  • Под капотом Swift: Механизмы управления памятью Swift для классов, совместимых с Objective-C (наследники от NSObject), также используют эту инфраструктуру runtime, включая Side Table, для слабых ссылок (weak).

Практический пример

Рассмотрим, как это работает на практике:

// Объявляем два слабых указателя
__weak id weakObj1 = nil;
__weak id weakObj2 = nil;

@autoreleasepool {
    // Создаем объект. Пока слабых ссылок нет, SideTable для него, скорее всего, не создана.
    NSObject *strongObj = [[NSObject alloc] init];

    // Создаем первую слабую ссылку. Runtime, вероятно, создаст или активирует SideTable
    // и добавит запись для `weakObj1` в weak_table.
    weakObj1 = strongObj;
    weakObj2 = strongObj;

    NSLog(@"Внутри пула: weakObj1 = %@", weakObj1); // Выведет адрес объекта

    // Выход из пула, `strongObj` разрушается, начинается деаллокация.
}
// На этом этапе деаллокация объекта завершена.
// Runtime прошел по weak_table в SideTable и обнулил ВСЕ слабые ссылки на этот объект.

NSLog(@"Вне пула: weakObj1 = %@, weakObj2 = %@", weakObj1, weakObj2);
// Обе переменные будут равны `nil`.

Итог

Таким образом, Side Table — это фундаментальный и старый компонент Objective-C Runtime, существующий с iOS 1.0. Он не был "введен" в какой-то конкретной версии как новая функция для разработчиков, а всегда работал под капотом. Его понимание критически важно для глубокого отладки проблем с памятью, циклами сильных ссылок и корректной работой weak-свойств, особенно при работе с большими и сложными кодобазами на Objective-C и смешанных проектах со Swift.

С какой версии iOS появился Side Table? | PrepBro