Как проверить счетчик ссылок в режиме 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, и даже если вы можете его увидеть, номер, который он возвращает, для вас бессмысленен. Если вы хотите, вы должны делать профилирование памяти в инструментах с инструментами утечки и распределения. Это лучший способ посмотреть и увидеть, как ваше приложение выделяет память и ловит любое неправильное использование памяти.
используйте инструменты и найдите объект, который вы хотите отслеживать, путем поиска имени класса или адреса указателя, если он у вас есть в "списке объектов".
когда вы его обнаружили, нажмите стрелку раскрытия на экземпляре. Это приводит вас к просмотру истории для сохраняет и relases.
Если вы развернете вид детали правой стороны, вы также увидите callstack для каждого сохранения / выпуска.
Я считаю, что единственный способ-профилировать ваше приложение с помощью инструмента распределения. Вам нужно будет нажать на информационный дескриптор ("i" рядом с распределением в левой панели) и нажать "запись ссылок". Затем вы можете профилировать свое приложение и выполнить поиск определенного класса, который вы хотите проверить. Оттуда вы можете найти счет сохранения в расширенной области сведений для каждого экземпляра класса.
вы также можете сделать это, используя утечки (так как я верьте, что это вариация инструмента распределения).
получить объект retainCount
?
вы можете просто сделать точку останова и ввести команду ниже, чтобы получить объект retainCount
po object.retainCount