Когда освобождается таблица состояний (state table) при ARC
Что проверяют
Знаете ли вы, как ARC устроен внутри, а не только правило «счётчик дошёл до нуля». Под «таблицей состояний» здесь почти всегда имеют в виду side table, боковую таблицу счётчиков. Следом обычно спрашивают, почему после deinit память объекта может ещё не освободиться и как это связано с weak и unowned.
Как отвечать
У нативного Swift-объекта счётчики лежат прямо в заголовке, рядом с указателем на метаданные. Side table появляется не у каждого объекта, а по требованию:
- когда создаётся: при первой
weak-ссылке на объект, в редких случаях ещё при переполнении встроенного счётчика. Слабая ссылка после этого указывает не на сам объект, а на таблицу; - что в ней: указатель на объект и все три счётчика, strong, unowned и weak, плюс флаги состояния;
- strong дошёл до нуля: вызывается
deinit, освобождаются свойства. Объект становится деинициализированным, но его память ещё занята, если осталисьunowned-ссылки; - unowned дошёл до нуля: освобождается память самого объекта. Таблица остаётся, если на неё смотрят слабые ссылки, и любая из них при чтении вернёт
nil; - weak дошёл до нуля: освобождается сама side table. Она живёт дольше объекта, пока не исчезнет последняя переменная со слабой ссылкой.
Такая схема работает со Swift 4. Раньше слабые ссылки указывали на объект напрямую и держали его память до своего обнуления, а таблица позволила отдавать память объекта сразу, оставляя маленький блок со счётчиками.
Для объектов Objective-C картина другая: там глобальные SideTables, поделённые на полосы по адресу объекта. Они не освобождаются вовсе, а при dealloc рантайм удаляет запись объекта и обнуляет все его weak-ссылки.
Где спотыкаются
Отвечают общим рассказом про retain count и deinit, так и не сказав, что таблица и объект освобождаются в разные моменты.
Думают, что side table есть у каждого экземпляра. Без слабых ссылок её нет, счётчики живут в заголовке объекта.
Путают Swift и Objective-C: переносят на Swift глобальную хэш-таблицу слабых ссылок или, наоборот, считают, что ObjC-таблица освобождается вместе с объектом.