Как проверить счетчик ссылок в режиме ARC?
Я использовал для проверки того, что некоторые из моих переменных имели ожидаемый счет сохранения, используя [myVar retainCount] под отладчиком, особенно для var, у которого не было пользовательского dealloc.
Как вы это делаете в режиме ARC? Как вы гарантируете отсутствие утечек памяти?
Примечание. Я понимаю, что ARC должна справиться с этим для меня, но жизнь далека от совершенства, и в реальной жизни у вас есть объекты, которые иногда выделяются сторонними библиотеками (с использованием сохранения?) и никогда не освобождаются.
Изображение, которое я делаю:
MyObj *myObj=[[MyObj alloc] init];
тогда я вызываю
[somethingElse doSomethingWithMyObj:myObj];
а затем я делаю
myObj=NULL;
Если моя программа работает нормально, я ожидаю, что myObj будет уничтожен, но похоже, что это не так...
Итак, как я могу отслеживать это, особенно если somethingElse не управляется мной?
Теперь о инструментах: кажется очень сложно запускать инструменты памяти на моем mac (с 5 мегабайтами) без перезагрузки mac и начать с нуля. Это действительно раздражает! Инструменты продолжают сбой даже до запуска программы, так же как есть альтернативное решение?
Ответы
Ответ 1
Вы можете использовать CFGetRetainCount
с объектами Objective-C, даже в ARC:
NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));
Это не, особенно полезно для отладки, по причинам, подробно описанным в другом месте. Если вам нужно понять, где объект будет сохранен и выпущен, ознакомьтесь с этим ответом за помощью с помощью инструмента Allocations.
Единственный случай, когда я обнаружил, что проверка количества удержания действительно полезен, - это метод dealloc
, когда что-то сохраняет и автореализует освобожденный объект. Это приведет к сбою позже, когда пул авторезистов будет слит. Вы можете определить причину этого, проверив количество удержаний до и после каждого сообщения. Таким образом, я обнаружил, что метод observationInfo
(который обычно используется только для отладки) сохраняет и автореализовывает self
. Однако даже такую проблему обычно можно решить, не изучая счетчик удержания, просто обернув все тело dealloc
в блок @autoreleasepool
.
Однако счет сохранения может быть использован, чтобы узнать о реализации некоторых классов. (Только для развлечения или любопытства! Никогда не полагайтесь на недокументированные детали реализации в производственном коде!)
Например, попробуйте сразу же в @autoreleasepool
в main
:
NSNumber *n0 = [[NSNumber alloc] initWithInt:0];
NSLog(@"0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef)n0));
// Prints 2 in my test
Итак, NSNumber
вероятнее всего кэширует (или, по крайней мере, повторно использует) некоторые экземпляры. Но не другие:
n0 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n0));
// Prints 1 - I am the sole owner of this instance. There could be weak
// or unretained references to it, but no other strong references.
NSNumber *n1 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints 1 again. New instance with same value as prior instance.
// You could of course compare pointers to see that they are separate
// instances.
Вы даже можете обнаружить, что NSNumber
возвращает singleton, если вы alloc
, но не инициализируете:
n1 = [NSNumber alloc];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints -1.
(Обратите внимание, что вы также можете узнать много деталей о NSNumber
, посмотрев исходный код Core Foundation, который доступен в http://opensource.apple.com. Но кто знает, что вы можете найти, если вы посмотрите на сохранение количества объектов, которые не являются бесплатными для мостов с объектами в Core Foundation?)
Ответ 2
Нет. ARC управляет управлением памятью для вас и не позволяет вам называть keepCount, и даже если вы его видите, номер, который он возвращает, не имеет смысла для вас. Если вы хотите, чтобы вы делали профилирование памяти в Инструментах с помощью инструментов "Утечки и распределения". Это лучший способ посмотреть и посмотреть, как ваше приложение распределяет память и улавливает любое неправильное использование памяти там.
Ответ 3
Вы никогда не должны использовать saveCount для чего-либо, с ARC или без него.
Когда использовать -retainCount?
Ответ 4
Используйте инструменты и найдите объект, который вы хотите отслеживать, ища имя класса или адрес указателя, если он у вас включен в "Список объектов".
Когда вы его разместите, нажмите стрелку раскрытия на экземпляре. Это приводит к просмотру истории для сохранения и отношения.
Если вы разберете подробный вид справа, вы также увидите столбец для каждого сохранения/выпуска.
![Instruments showing object history and callstack detail]()
Ответ 5
Я считаю, что единственный способ - профилировать ваше приложение с помощью инструмента Allocations. Вам нужно будет щелкнуть по информационному дескриптору ( "i" рядом с "Распределение в левой панели" ) и нажать "Записать количество ссылок". Затем вы можете профилировать свое приложение и выполнять поиск определенного класса, который вы хотите проверить. Оттуда вы можете найти счет сохранения в панели расширенной детали для каждого экземпляра класса.
Вы также можете сделать это с помощью утечек (так как я считаю это вариацией инструмента Allocations).
Ответ 6
Получить объект retainCount
?
Вы можете просто сделать точку останова и ввести команду ниже, чтобы получить объект retainCount
po object.retainCount
Ответ 7
Нет. Apple заявляет, что вам не нужно, поскольку ARC будет обрабатывать ее для вас.
Ответ 8
Вы не должны заботиться о retainCount
. Вы должны написать свой код правильно и ожидать, что библиотеки, которые вы используете, также написаны правильно.