Как проверить счетчик ссылок в режиме ARC?

я использовал, чтобы проверить, что некоторые из моих переменных имели ожидаемый счетчик сохранения, используя [myVar retainCount] под отладчиком, особенно для var, у которого не было пользовательского разрешения.

как это сделать в режиме ARC? Как вы убедитесь, что нет утечек памяти?

примечание: Я понимаю, что ARC должен справиться с этим для меня, но жизнь далека от совершенства, и в реальной жизни у вас есть объекты, которые иногда выделяются сторонними библиотеками (используя retain?) и никогда не освобождался.

изображение, которое я делаю это:

MyObj *myObj=[[MyObj alloc] init];

тогда я зову

[somethingElse doSomethingWithMyObj:myObj];

и потом, я делаю

myObj=NULL;

Если моя программа работает нормально, я ожидаю, что myObj уничтожается, но, похоже, это не так...

Итак, как я могу отслеживать это, особенно если somethingElse не управляется мной?

Теперь об инструментах: кажется чрезвычайно трудно запустить инструменты памяти на моем mac (с 5 Мег) без перезагрузка mac и запуск с нуля. Это действительно раздражает! Инструменты продолжают сбой еще до запуска программы, так что есть ли решение alterante?

7 ответов


можно использовать CFGetRetainCount С объектами Objective-C, даже под дугой:

NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));

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

единственный случай, когда я обнаружил, что изучение количества удержаний действительно полезно, - это dealloc метод, когда что-то сохраняет и autoreleases объект освобождается. Это приведет к сбою позже, когда пул autorelease будет осушен. Вы можете точно определить причину этого, проверив счетчик сохранения до и после каждого сообщения. Таким образом, я обнаружил, что the observationInfo метод (что само по себе обычно полезно только для отладки) сохраняет и autoreleases 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 возвращает синглтон, если вы alloc но не инициализировать:

n1 = [NSNumber alloc];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints -1.

(обратите внимание, что вы также можете узнать много подробностей о NSNumber взглянув на исходный код Core Foundation, который доступен по адресу http://opensource.apple.com. Но кто знает, что вы можете найти, если посмотрите на количество объектов, которые не связаны с объектами в Core Foundation?)


ты не знаешь. ARC обрабатывает управление памятью для вас и не позволяет вам вызывать retainCount, и даже если вы можете его увидеть, номер, который он возвращает, для вас бессмысленен. Если вы хотите, вы должны делать профилирование памяти в инструментах с инструментами утечки и распределения. Это лучший способ посмотреть и увидеть, как ваше приложение выделяет память и ловит любое неправильное использование памяти.


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

когда использовать -retainCount?


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

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

Если вы развернете вид детали правой стороны, вы также увидите callstack для каждого сохранения / выпуска.

Instruments showing object history and callstack detail


Я считаю, что единственный способ-профилировать ваше приложение с помощью инструмента распределения. Вам нужно будет нажать на информационный дескриптор ("i" рядом с распределением в левой панели) и нажать "запись ссылок". Затем вы можете профилировать свое приложение и выполнить поиск определенного класса, который вы хотите проверить. Оттуда вы можете найти счет сохранения в расширенной области сведений для каждого экземпляра класса.

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


получить объект retainCount?

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

po object.retainCount

ты не знаешь. Apple говорит, что вам не нужно, так как ARC будет обрабатывать его для вас.