Почему NSNumber такой странный retainCounts? - PullRequest
1 голос
/ 18 марта 2009
NSNumber* n = [[NSNumber alloc] initWithInt:100];
NSNumber* n1 = n;

Почему в приведенном выше коде значение n's retainCount равно 2? Во второй строке кода я не использовал retain для увеличения числа retainCount.


Я обнаружил странную ситуацию. На самом деле retainCount зависит от начального номера:

NSNumber *n = [[NSNumber alloc] initWithInt:100]; 
// n has a retainCount of 1

NSNumber *n2 = [[NSNumber alloc] initWithInt:11]; 
// n has a retainCount of 2

Ответы [ 5 ]

6 голосов
/ 18 марта 2009

Исходя из этой ссылки здесь , возможно, что происходит некоторая оптимизация под прикрытием для общих номеров NSN (что может случиться не во всех реализациях, поэтому возможная причина, почему @ dizy's retainCount равна 1). 1003 *

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

Какой адрес у n и n1? Я подозреваю, что они одинаковы.

NSNumber* n = [[NSNumber alloc] initWithInt:100];

NSLog(@"Count of   n : %i",[n retainCount]);

NSNumber* n1 = n;

NSLog(@"Count of   n : %i",[n retainCount]);
NSLog(@"Count of   n1: %i",[n1 retainCount]);
NSLog(@"Address of n : %p", n);
NSLog(@"Address of n1: %p", n1);

Судя по вашему обновлению, ссылка, которую я вам дал, почти наверняка является проблемой. Кто-то выполнил тест и обнаружил, что номера NSN от 0 до 12 дадут вам дубликаты уже созданных (на самом деле они могут быть созданы платформой даже до того, как пользователь их запросит). Другие выше 12, кажется, дали счет сохранения 1. Цитата:

Из небольшой проверки, которую я смог сделать, похоже, что вы получите «общие» версии целочисленных NSNumbers для значений в диапазоне [0-12]. Все, что больше 12, дает вам уникальный экземпляр, даже если значения равны. Почему двенадцать? Понятия не имею. Я даже не знаю, является ли это жестким числом или косвенным.

Попробуйте это с 11, 12 и 13 - я думаю, вы обнаружите, что 13 является первым, кто даст вам не-общий NSNumber.

5 голосов
/ 18 марта 2009

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

В качестве примера того, почему рассмотрение количества сохранений ненадежно, это совершенно законный класс, который подчиняется контракту API и будет вести себя правильно при любых обстоятельствах:

@implementation CrazyClass
  - (id)retain {
      for(int i=0; i<100; i++) {
          [super retain];
      }
  }

  - (void)release {
      for(int i=0; i<100; i++) {
          [super release];
      }
  }
@end

… но если вы проверили его количество, вы бы подумали, что у вас есть «проблема».

Этот точный случай не случается слишком часто на практике, но он иллюстрирует, почему наблюдение за счетом удержания бесполезно для определения, если что-то не так. Объекты остаются за кадром с помощью кода, находящегося вне вашего контроля. Например, NSNumber иногда будет кэшировать экземпляры. Объекты автоматически высвобождаются, что не отражается в счетчике хранения. Может случиться много вещей, которые могут сбить с толку счет. Некоторые классы могут даже не сохранять количество сохраняемых файлов там, где их можно увидеть.

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

5 голосов
/ 18 марта 2009

Stop. Просто остановись. Никогда посмотрите на retainCount объекта. Когда-либо. Это никогда не должно было быть API и доступно. Вы просите боли.

Слишком много всего происходит для retainCount, чтобы быть осмысленным.

4 голосов
/ 18 марта 2009

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

Почему? Потому что это не учитывает autorelease с. Если объект retain ed и впоследствии autorelease d, его retainCount будет увеличиваться, но, насколько вам известно, его real счет сохранения не изменился. Единственный способ получить реальное количество сохраняемых объектов - это подсчитать, сколько раз он был добавлен в любой из пулов авто-релизов в цепочке пулов авто-релизов, и попытка сделать это вызывает проблемы.

В этом случае retainCount равен 2, потому что где-то внутри alloc или initWithInt: объект находится retain ed и autorelease d. Но вам не нужно знать или заботиться об этом, это деталь реализации.

2 голосов
/ 18 марта 2009

Я думаю, у тебя что-то еще происходит ...

    NSNumber* n = [[NSNumber alloc] initWithInt:100]; 
    NSNumber* n1 = n;
    NSLog(@"n = %i",[n retainCount]);

Результат 1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...