0

I am new to iPhone programming. I have created a Window based application. Following is my code:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    UILabel *myLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(50, 200, 200, 80)];
    myLabel1.text = @"Prasad";
    NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
    [myLabel1 release];
    NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
    [window makeKeyAndVisible];
    return YES;
}

Q1. When I release mylabel1, NSLog statement following the release statement still prints retainCount as 1 whereas ideally it should print 0. Also the application is running absolutely fine.

Now consider the following code: (which is similar to above code except for adding one NSLog statement: NSLog(@"Bingoooooooo Memeory Released"); )

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    UILabel *myLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(50, 200, 200, 80)];
    myLabel1.text = @"Prasad";
    NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
    [myLabel1 release];
    NSLog(@"Bingoooooooo Memeory Released");
    NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
    [window makeKeyAndVisible];
    return YES;
} 

Now my query is,
1. When I run the above code the application gets crashed after printing NSLog(@"Bingoooooooo Memeory Released"); Why is the application getting crashed just by adding the NSLog(@"Bingoooooooo Memeory Released") statement whereas in the First Code the application is not getting crashed.

Matthias Bauch
  • 88,097
  • 19
  • 217
  • 244
Prazi
  • 335
  • 1
  • 5
  • 18
  • Prazi, please take the time to properly format the code in your question, it is much more likely someone will be able to help you then. – Johannes Rudolph Jan 29 '11 at 08:14
  • send your application crash report. – Tirth Jan 29 '11 at 09:22
  • 2
    If `retainCount` ever returned zero, the singularity would be achieved and the universe would end. At least, it would for your app. – bbum Jan 29 '11 at 17:40

2 Answers2

4

First of all, do not ever look at retainCount. It is not reliable and is influenced by a lot of internal factors. The second version of your code causes crashes because: 1) You create a label so its retain count is 1 2) You release it so its retain count is 0 3) You send a message to it. Because its retain count is 0, it's already been deallocated so the app crashes.

Have no idea why the first version does not crash

tux91
  • 1,654
  • 10
  • 16
  • @Prazi See the answer of Dave Delong http://stackoverflow.com/questions/4636146/when-to-use-retaincount/4636477#4636477 – Robin Jan 29 '11 at 08:47
1

The documentation for -retainCount has the following warning:

Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

And, as various other answers about retain count on Stack Overflow say, do not rely on -retainCount.


That said, answering your questions:

Q1. When I release mylabel1, NSLog statement following the release statement still prints retainCount as 1 whereas ideally it should print 0.

Let’s consider your object isn’t in an autorelease pool. If the object has retain count 1 and receives a release message, it’ll be deallocated. What’s the point of decrementing the retain count of a deallocated object? The runtime doesn’t do it because it’s a pointless operation since the object is ceasing to exist.

1. When I run the above code the application gets crashed after printing NSLog(@"Bingoooooooo Memeory Released"); Why is the application getting crashed just by adding the NSLog(@"Bingoooooooo Memeory Released") statement whereas in the First Code the application is not getting crashed.

First of all, notice that since myLabel1 is not owned by other objects/code it is deallocated when you send [myLabel1 release]. If you send further messages to that deallocated object (e.g. [myLabel1 retainCount]), your code will potentially crash, so don’t do that.

When an object is deallocated, the memory occupied by the object is marked as available for use. Depending on the subsequent instructions, that memory region previously occupied by the object might or might not be rewritten. Until it is rewritten, the deallocated object can be referenced — it’s a ghost object, and not reliable at all. In your case, adding another NSLog() instruction or some other factor is causing that memory region to be rewritten.