Что такое утечка памяти и как она возникает?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Утечка памяти (memory leak) — это ситуация, когда выделенная память более недоступна для использования программой (потеряны все ссылки на нее), но при этом она не была освобождена операционной системой.
Причины возникновения утечки памяти в iOS:
-
Циклические сильные ссылки (Retain Cycles): Два или более объекта ссылаются друг на друга сильными ссылками, предотвращая их деаллокацию, даже если на них больше нет внешних ссылок.
class Person { var name: String var apartment: Apartment? init(name: String) { self.name = name print("\(name) is being initialized") } deinit { print("\(name) is being deinitialized") } } class Apartment { let unit: String weak var tenant: Person? // weak ссылка предотвращает цикл init(unit: String) { self.unit = unit print("Apartment \(unit) is being initialized") } deinit { print("Apartment \(unit) is being deinitialized") } } // Пример создания цикла сильных ссылок (если бы tenant был强 ссылкой) // var john: Person? = Person(name: "John Appleseed") // var unit4A: Apartment? = Apartment(unit: "4A") // john?.apartment = unit4A // unit4A?.tenant = john // strong reference here would cause a cycle -
Неправильное использование замыканий (Closures): Замыкание захватывает сильную ссылку на внешний объект (например,
self), который владеет этим замыканием.class ViewController: UIViewController { var networkRequestCompletionHandler: (() -> Void)? func fetchData() { // Если бы здесь использовался явный self без capture list: // networkRequestCompletionHandler = { // self.updateUI() // self is strongly captured // } // Правильно с capture list: networkRequestCompletionHandler = { [weak self] in self?.updateUI() // self is weakly captured } } func updateUI() { // update UI } deinit { print("ViewController is being deinitialized") } }Использование
[weak self]или[unowned self](unownedдля случаев, когда объект, захватываемый замыканием, гарантированно живет дольше замыкания) предотвращает сильное захватывание. -
Отсутствие отписки от наблюдателей/подписок: Объекты, подписанные на уведомления (
NotificationCenter), KVO или другие механизмы обратного вызова, могут утекать, если они не отписываются во время деаллокации.class ObserverClass { init() { NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: Notification.Name("MyNotification"), object: nil) } @objc func handleNotification() { // handle notification } deinit { // Необходимо отписаться, иначе экземпляр может утечь NotificationCenter.default.removeObserver(self) print("ObserverClass is being deinitialized") } } -
Удержание ссылок в статических или глобальных переменных: Если объект удерживается сильной ссылкой из статической или глобальной переменной, он никогда не будет деаллоцирован.
-
Неправильное использование C-указателей и Core Foundation объектов: Manual memory management required when bridging Swift/Objective-C with C APIs or Core Foundation objects. Incorrect handling of
retain,release,freefunctions can lead to leaks or crashes.
Утечки памяти со временем приводят к исчерпанию доступной памяти приложения, что может вызвать замедление работы или аварийное завершение программы из-за нехватки ресурсов.