Подтвердить что ты не робот

Понимание глубины удержания

Допустим, у нас есть три объекта: бабушка, родитель и ребенок. Бабушка и дедушка сохраняют родителя, родитель сохраняет ребенка, а ребенок сохраняет родителя. Бабушка и дедушка выпускают родителя.

Что произойдет в этом случае?

4b9b3361

Ответ 1

Если нет другой ссылки на родителя или ребенка, они становятся сиротами. Но цикл сохранения между родителем и ребенком не позволяет освободиться, и они теряют память.

Ребенок никогда не должен сохранять родителя. Если что-нибудь, используйте слабую ссылку в дочернем элементе, чтобы сохранить ссылку на родителя.

Ответ 2

Сохранение цикла - это условие. Когда 2 объекта сохраняют ссылку друг на друга и сохраняются, он создает цикл сохранения, поскольку оба объекта пытаются сохранить друг друга, что делает невозможным его освобождение.

Здесь "Дедушка" сохраняет "родителя", а "родитель" сохраняет "ребенка", где "ребенок" сохраняет "родителя". Здесь устанавливается цикл сохранения между родителем и ребенком. После освобождения бабушки и дедушки родитель и ребенок становятся сиротами, но удержание счета родителя не будет равным нулю, поскольку оно сохраняется у ребенка и, следовательно, вызывает проблему с управлением памятью.

Существует два возможных решения:

1) Используйте слабый указатель на родительский, то есть ребенок должен использовать слабую ссылку на родителя, которая не сохраняется.

2) Используйте методы "закрыть", чтобы разбить циклы удержания.

http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html

Ответ 3

В простом случае рассмотрим два объекта A и B, где A создает и сохраняет B. Когда A создается, он создает B. Когда тот, кто создал A, наконец-то выпускает его, счетчик удержания падает до нуля и освобождается. Если метод dealloc вызывает освобождение на B, показатель сохранения B также падает до нуля, и он также освобождается. [Это предполагает, что никто не сохранил A или B, потому что я делаю все просто.]

Но что произойдет, если B нуждается в ссылке обратно в A, и он сохранит A? Тот, кто создал A, может освободить его. Но так как B также сохранил A, показатель удержания не будет равен нулю. Точно так же, поскольку A сохраняет B, B сохраняет отсчет также не будет идти к нулю. Ни один из них не будет освобожден. Даже если B вызывает метод release в своем собственном dealloc, это не имеет значения, потому что этот метод никогда не будет вызван.

В этот момент у вас есть утечка памяти, потому что у вас нет ссылки на A или B, хотя они оба все еще существуют. Если A или B делает что-то более интенсивным, то вы также можете протекать процессорное время на нежелательные объекты.

В вашем случае A является родителем, а B является дочерним, а любой, кто создал A, является дедушкой.

Ответ 4

Цикл удержания - это цикл, который происходит, когда объект А сохраняет объект B, а объект B сохраняет объект A. В этой ситуации, если один из объектов освобожден:

  • Объект A не будет освобожден, поскольку объект B содержит ссылку на it (сохранить count > 0).
  • Объект B никогда не будет освобожден, если объект А имеет ссылку на него (сохранить count > 0).
  • Но объект A никогда не будет освобожден, поскольку объект B содержит ссылку на него (сохранить count > 0).
  • до бесконечности

Таким образом, эти два объекта будут просто зависеть в памяти для жизни программы, даже если они должны, если все будет работать должным образом, освободиться.

Ответ 5

Когда grandparent освобождает родителя, родитель все еще жив, так как ребенок сохраняет родителя.

Ответ 6

Сохраняемый цикл - это условие, когда объекты 2 сохраняют ссылку друг на друга и сохраняются, создают цикл сохранения, поскольку оба объекта старайтесь удерживать друг друга, делая невозможным освобождение.


Пример: Человек живет в отделе, отдел имеет одного человека.

@class Department;

@interface Person:NSObject
@property (strong,nonatomic)Department * department;
@end

@implementation Person
-(void)dealloc{
    NSLog(@"dealloc person");
}

@end
@interface Department: NSObject
@property (strong,nonatomic)Person * person;
@end

@implementation Department
-(void)dealloc{
    NSLog(@"dealloc Department");
}
@end

Затем назовите его следующим образом:

- (void)viewDidLoad {
    [super viewDidLoad];
    Person * person = [[Person alloc] init];
    Department * department = [[Department alloc] init];
    person.department = department;
    department.person = person;
}

Вы не увидите журнал dealloc, это круг сохранения.

Ответ 7

Поскольку у объекта P сохраняется значение 1, когда оно отпущено, его keepCount переходит в 0, и его метод dealloc вызывается; Это, в свою очередь, вызывает освобождение на объекте C, счетчик которого также переходит в 0; и его метод dealloc вызывается.

Оба объекта P и C освободятся.

Когда вызывается метод dealloc объекта C, в свою очередь вызывается публикация объекта объекта GP, но поскольку GP имеет значение удержания 2, счет сохранения уменьшается до 1, и он продолжает зависать.

Ответ 8

Дедушка: Джон Родитель: Тед Ребенок: Мэри

Вот мой пример использования телефонного звонка для иллюстрации:

  • Джон звонит Теду и хочет сделать телефонную конференцию с Мэри.

  • Тед говорит Джону: "Повесьте трубку, и я позвоню Мэри"

  • Тед оставляет Джона в ожидании и звонит Мэри, которая быстро отвечает на звонок.

  • Мэри говорит Теду: "Слей мой звонок с Джоном, и я не буду вешать трубку, пока я не закончу"

  • Тед, не получив ответа от Джона некоторое время, оставляет призыв сделать что-то еще.

  • Джон идет, чтобы объединить звонки с Тедом и Мэри, а затем внезапно умирает.

  • Мэри застряла на линии с Джоном, но никогда не повесит трубку, потому что Джон не вернется!