Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I verify reference count in ARC mode?

I used to verify that some of my variables had the expected retain count using [myVar retainCount] under the debugger, especially for var that did not have a custom dealloc.

How do you do this in ARC mode? How do you ensure that there are no memory leaks?

Note: I understand that ARC should handle this for me, but life is far from being perfect, and in real life you have objects that are sometimes allocated by third party libraries (using retain?) and never deallocated.

Image that I do this:

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

then I call

[somethingElse doSomethingWithMyObj:myObj]; 

and later, I do

myObj=NULL; 

If my program is working fine, my expectation is that myObj is being destroyed, but it appears not to be the case...

So how can I track this, especially if somethingElse is not managed by me?

Now, about the tools: it seems extremely hard to run memory tools on my mac (with 5 Meg) without rebooting the mac and starting from scratch. This is really annoying! Instruments keep crashing even before the program has started, so is there an alterante solution?

like image 839
tomsoft Avatar asked Jan 14 '12 15:01

tomsoft


People also ask

How do I check my reference count?

CFGetRetainCount() can be used to get the referenceCount of an object. You can do this by putting break points or using print(CFGetRetainCount(CFTypeRef!)) function in your code .

What does a retain count represents in ARC?

Retain Count represents number of owners for a particular object. It is zero till object does not have any owners. Increase in one ownership claim will cause retain count to increase by 1 and decrease will cause it to decrement by 1. Example: - Class A object is created using alloc/init and retain count is 1.

How do I get a reference count in Swift?

You can always check the reference count of a variable by using the CFGetRetainCount function. Note: Reference counting is done only to manage memory for reference types (e.g., classes and closures).

What is swift Retain count?

An essential concept in ARC is the retain count, which is a number that keeps track of how many objects are “holding onto” to another object. ARC only applies to reference types such as classes, and not to value types like structs. Value types are copied, so they don't work with references.


1 Answers

You can use CFGetRetainCount with Objective-C objects, even under ARC:

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

This is not particularly useful for debugging, though, for reasons amply described elsewhere. If you need to understand where an object is being retained and released, check out this answer for help using the Allocations instrument.

The only case I've found where examining the retain count is actually useful is in a dealloc method, when something retains and autoreleases the object being deallocated. This will cause a crash later when the autorelease pool is drained. You can pinpoint the cause of this by checking the retain count before and after each message. In this way I discovered that the observationInfo method (which is itself usually only useful for debugging) retains and autoreleases self. However, even this sort of problem can usually be solved without examining the retain count, simply by wrapping the entire body of dealloc in an @autoreleasepool block.

However, the retain count can be used to learn about the implementation of some classes. (Only do this for entertainment or curiosity! Never rely on undocumented implementation details in production code!)

For example, try this immediately inside the @autoreleasepool in main:

NSNumber *n0 = [[NSNumber alloc] initWithInt:0]; NSLog(@"0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef)n0)); // Prints 2 in my test 

So NSNumber likely caches (or at least reuses) some instances. But not others:

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. 

You can even discover that NSNumber returns a singleton if you alloc but don't initialize:

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

(Note that you can also learn many details about NSNumber by looking at the Core Foundation source code, which is available at http://opensource.apple.com. But who knows what you might find if you look at the retain count of objects that aren't toll-free-bridged with objects in Core Foundation?)

like image 134
rob mayoff Avatar answered Oct 19 '22 03:10

rob mayoff