Как проверить количество ссылок в режиме ARC? - PullRequest
34 голосов
/ 14 января 2012

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

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

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

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

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

тогда я звоню

[somethingElse doSomethingWithMyObj:myObj];

и позже я делаю

myObj=NULL;

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

Так как я могу отследить это, особенно если что-то еще не управляется мной?

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

Ответы [ 7 ]

99 голосов
/ 22 января 2012

Вы можете использовать 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 возвращает синглтон, если вы alloc, но не инициализируете:

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

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

41 голосов
/ 14 января 2012

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

31 голосов
/ 14 января 2012

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

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

15 голосов
/ 06 июня 2013

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

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

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

Instruments showing object history and callstack detail

3 голосов
/ 14 января 2012

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

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

2 голосов
/ 24 октября 2015

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

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

po object.retainCount
0 голосов
/ 14 января 2012

Ты не.Apple говорит, что вам не нужно, так как ARC справится с вами.

...