Что такое сайд таблица (side table) в контексте weak ссылок и как она работает
Что проверяют
Знаете ли вы, как рантайм Swift на самом деле превращает слабую ссылку в nil, а не только то, что weak разрывает цикл. Следом спрашивают, чем weak отличается от unowned на этом уровне и что происходит с памятью объекта после deinit.
Как отвечать
Начиная со Swift 4 в заголовке каждого объекта есть поле счётчиков ссылок. Пока слабых ссылок нет, strong и unowned счётчики лежат прямо в нём. Сайд таблица это отдельная структура в куче, которую рантайм создаёт лениво:
- когда появляется: при первой
weakссылке на объект или при переполнении встроенного счётчика. Поле в заголовке заменяется указателем на таблицу, и обратно объект её уже не теряет; - что хранит: strong, unowned и weak счётчики и указатель на сам объект;
- куда смотрит weak: слабая ссылка указывает не на объект, а на его сайд таблицу;
- чтение: при обращении к
weak varрантайм через таблицу проверяет, жив ли объект. Если он уже вdeinitили освобождён, возвращаетсяnil.
Порядок освобождения: strong счётчик дошёл до нуля, вызывается deinit. Память объекта освобождается, когда обнулится unowned счётчик, а сама сайд таблица живёт, пока на неё смотрят слабые ссылки. Так объект не держится в памяти целиком ради одной слабой ссылки: до Swift 4 weak указывал прямо на объект, и тот оставался «зомби», пока слабые ссылки не прочитают.
Хорошо сравнить с Objective-C: там глобальные SideTables с хэш-таблицей слабых ссылок, и при dealloc рантайм сам проходит по ним и обнуляет каждый указатель. В Swift обнуление ленивое, при чтении.
Где спотыкаются
Говорят, что сайд таблица «предотвращает утечки». Цикл разрывает сама слабая ссылка, таблица лишь даёт безопасно узнать, что объекта больше нет.
Думают, что таблица есть у каждого объекта. Она появляется только по необходимости, поэтому первая weak ссылка стоит аллокации, а доступ через неё медленнее, чем через сильную.
Путают с unowned: такая ссылка указывает прямо на объект и в nil не превращается. Обращение к unowned после deinit роняет приложение.