Что такое зомби-объект (zombie object) в iOS/macOS?

Ответ

Зомби-объект — это объект, память которого была освобождена (deallocated), но на который сохранилась "живая" ссылка. Попытка обращения по этой ссылке приводит к неопределённому поведению или крашу.

Причины появления:

  1. В Objective-C: Ошибки ручного управления памятью (MRC) или неправильное использование unsafe_unretained.
  2. В Swift: Использование unowned при обращении к уже освобождённому объекту или работа с небезопасными указателями (UnsafePointer).

Инструменты для отладки:

  • NSZombieEnabled (Objective-C): Флаг среды, который превращает освобождённые объекты в "зомби", логируя обращение к ним вместо немедленного краша.
  • Диагностика памяти в Xcode: Инструменты "Address Sanitizer" и "Zombie Objects" помогают находить такие ошибки.

Пример опасного кода на Swift:

class DataManager {
    func process() { print("Processing...") }
}

var unownedManager: Unowned<DataManager>? // Аналог unowned reference

func createManager() {
    let manager = DataManager() // Создаётся объект
    unownedManager = .some(manager)
    // manager выходит из области видимости и деинициализируется
}

createManager()
// Попытка доступа к освобождённой памяти -> КРАШ
// unownedManager!.value.process() // Runtime error: bad access

Как избежать:

  • Предпочитайте weak ссылки unowned, если есть вероятность, что объект может быть освобождён.
  • Используйте weak для делегатов и обратных вызовов.
  • Включайте инструменты санитизации памяти во время отладки.

Ответ 18+ 🔞

А, зомби-объекты, классика жанра! Это когда твой код превращается в ходячий пиздец, а ты даже не сразу понимаешь, откуда ноги растут.

Представь: ты освободил память, выкинул объект на помойку, а какая-то ссылка, блядь, всё ещё тянется к нему, как последний алкаш к пустой бутылке. Ты по этой ссылке пытаешься что-то сделать — а там уже труп, разлагающаяся память. И привет, краш, неопределённое поведение, ёперный театр! Твоё приложение просто накрывается медным тазом.

Откуда эта нечисть лезет? В старом добром Objective-C — это обычно ручное управление памятью, где ты, мудак, где-то недосчитался или пересчитал, или накосячил с unsafe_unretained. В Swift — это уже более изящные грабли: либо unowned ссылка, которая оказалась самоуверенной сукой и думала, что объект вечный, либо ты полез в дебри небезопасных указателей (UnsafePointer) и там всё просрал.

Чем ловить этих зомби? Есть, блядь, волшебные инструменты! В Objective-C — флаг NSZombieEnabled. Включаешь его, и освобождённые объекты вместо того чтобы тихо сдохнуть, превращаются в зомби. Они не крашнут тебя сразу, а начнут орать в лог: «Смотри, чувак, ты обращаешься к трупу, вот его адрес, иди разбирайся!» Просто сказка. В Xcode есть целая «Диагностика памяти». Включаешь «Address Sanitizer» или «Zombie Objects» — и они, как охотники на привидений, начинают подсвечивать тебе все эти косяки.

Вот, смотри, как на Swift можно самому себе ногу выстрелить:

class DataManager {
    func process() { print("Processing...") }
}

var unownedManager: Unowned<DataManager>? // Аналог unowned reference

func createManager() {
    let manager = DataManager() // Создаётся объект
    unownedManager = .some(manager)
    // manager выходит из области видимости и деинициализируется
}

createManager()
// Попытка доступа к освобождённой памяти -> КРАШ
// unownedManager!.value.process() // Runtime error: bad access

Видишь? Создали менеджера, запихнули на него unowned ссылку, функция отработала — и объект сдох. А ссылка-то осталась, дура, живая. Попробуй к ней обратиться — получишь bad access прямо в ебало, программа рухнет. Удивление пиздец.

Как не наступать на эти грабли? Правило простое, как три копейки: если есть хотя бы тень сомнения, что объект может испариться — используй weak, а не unowned. weak — это трусоватая, но умная ссылка. Она, если объект умер, сама становится nil. А unowned — это максималист, который верит в объект до последнего, а потом ведёт тебя прямиком в краш. Особенно это касается делегатов и всяких обратных вызовов — там weak должен быть твоей религией. И главное — не забывай во время отладки включать эти санитайзеры, Address Sanitizer там. Пусть работают, блядь, ищут за тебя эту гниль. Экономия нервов — овердохуища.