Подсчет ссылок или сохранение количества (управление памятью)

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

Мой вопрос, как вы можете видеть, метод dealloc вызывается только тогда, когда счет сохранения достигает нуля, то есть освобождается память для объекта RetainTracker. Однако проблема заключается в том, что, когда я записываю счет сохранения в методе dealloc, он все равно показывает счет сохранения 1. Почему это происходит?

Вот мой код:

#import <Foundation/Foundation.h>
@interface RetainTracker : NSObject

@end

@implementation RetainTracker

- (id)init {

    if (self = [super init]) {
        NSLog(@"init: Retain count of %lu",(unsigned long)[self retainCount]);
    }
    return self;
}

- (void)dealloc {

    NSLog(@"Dealloc called bye bye!==>%lu",(unsigned long)self.retainCount);
    [super dealloc];
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        RetainTracker *myRetainTracker = [RetainTracker new];

        [myRetainTracker retain]; // count-->2
        NSLog(@"The retain count is ==>%lu",(unsigned long)myRetainTracker.retainCount);

        [myRetainTracker release];// count -->1
        NSLog(@"The retain count is ==>%lu",(unsigned long)myRetainTracker.retainCount);

        [myRetainTracker retain];// count -->2
        NSLog(@"The retain count is ==>%lu",(unsigned long)myRetainTracker.retainCount);

        [myRetainTracker release];// count -->1
        NSLog(@"The retain count is ==>%lu",(unsigned long)myRetainTracker.retainCount);

        [myRetainTracker release];// count -->0
        NSLog(@"The retain count is ==>%lu",(unsigned long)myRetainTracker.retainCount);

    }
    return 0;
}

Вот журналы:

init: Retain count of 1
The retain count is ==>2
The retain count is ==>1
The retain count is ==>2
The retain count is ==>1
Dealloc called bye bye!==>1
The retain count is ==>1

2 ответа

Это не удивительно, release код, вероятно, выглядит так (в псевдокоде):

- (void)release {
   if (retainCount > 1) {
      retainCount -= 1
   } else {
      // no need to set the retainCount to 0 here,
      // the object now ends its existence
      [self dealloc]
   }
}

Кроме того, ваш последний NSLog фактически получает доступ к объекту, который больше не существует, что может привести к сбою.

Обратите внимание, что значение прочитано из retainCount никогда не следует полагаться. Это просто деталь реализации. Намного безопаснее думать retain а также release как передача права собственности.

От retainCount документация:

Не используйте этот метод.

а также

Этот метод не имеет значения при отладке проблем управления памятью. (...) очень маловероятно, что вы можете получить полезную информацию с помощью этого метода.

Переключите свой проект на ARC. Шутки в сторону. Я забыл все, что я знал о сохранении / освобождении три года назад. Помимо этого, сохранение количества объектов в процессе освобождения не имеет смысла. Бесполезно удивляться этому.

Другие вопросы по тегам