Objective C Nsstring* Property Retain Count Oddity

Objective C NSString* property retain count oddity

You've got a reference to an immutable string. Assignment doesn't need to copy the value (the string data) since it's immutable. If you do a mutable operation, like value = [newValue uppercaseString] then it should copy the bits into value, and value's retain count incremented.

NSString retain Count

The compiler is smarter than you.

It sees @"Hello world" and thinks "Aha! A constant string!"

It then sees [[NSString alloc] initWithString:@"Hello world!"] and thinks "Aha! An immutable object created with a constant string!"

It then collapses both of them down into a single NSConstantString, which has a retainCount of UINT_MAX, so that it can never be released.

NSString retainCount is 2147483647

It is 2147483647 because you looked. Don't look and it will be the value you expect.

Seriously. Don't call retainCount. Not ever. It is useless.

Why it is such a ridiculous number is because of an implementation detail. @"..." is a constant string. NSString can recognize constant strings and decides that your particular code has no need of a second space consuming copy of a constant immutable string and, thus, returns the already existing constant string.

I.e. a singleton. Of a class whose instances are only ever created by the compiler. For which retain/release/autorelease/retainCount are utterly devoid of meaning.

As for why it is 2147483647, a picture is worth a thousand words. Or, in this case, 31 set bits.
negative one expressed in far too many digits

How to find Retain Count of the Objects?

NSString *str1=@"Hai";
NSString *str2=str1;
NSSstring *str3=[str2 copy];

NSLog(@"COUNT %lu",(unsigned long)[str1 retainCount]);
NSLog(@"COUNT %lu",(unsigned long)[str2 retainCount]);
NSLog(@"COUNT %lu",(unsigned long)[str3 retainCount]);

been having a little confusion about the retainCount of NSURLConnection

Everything is absolutely OK here: NSURLConnection must retain itself to be sure that it can deliver data to the delegate (and to do that it must not be deallocated). If there is no delegate, then nobody listens to that connection and there is no reason to perform anything, so it doesn't retain itself. Connection then releases itself after:

-(void) connectionDidFinishLoading:(NSURLConnection*) connection

OR

-(void) connection:(NSURLConnection*) connection didFailWithError:(NSError*) error

From your example:

. . .
NSURLConnection *_conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
. . .
[_conn release];

if retainCount was 1, then after [_conn release] the object would be deallocated immediately and there would be no loading at all.

To all of you, who says that retainCount works incorrectly: you just don't know how it works. As for NSString 'oddity': this is not oddity, this is just performance optimization. 2147483647 retain count means that object is constant in memory (and is deleted when app terminates). This is done when the value is known during compilation:

NSString* str = @"12345"; //has 2147483647 retain count.

ios: Retain count of 2147483647?

You initiate your NSString object with string literal and 2 following things happen:

  1. As NSString is immutable -initWithString: method optimizes string creation so that your testString actually points to a same string you create it with (@"Test")
  2. @"Test" is a string literal and it is created in compile time and lives in a specific address space - you cannot dealloc it, release and retain does not affect its retain count and it is always INT_MAX

With all mentioned above you still should work with your string object following memory management rules (as you created it with alloc/init you should release it) and you'll be fine

Objective C - Crash due to double release?

Why does it not crash?

Because the objects in question are object literals, which are treated somewhat differently. Basically, such objects are never deallocated. See Objective C NSString* property retain count oddity for a full explanation.

If you change the second line like this:

[array addObject:[stringWithFormat:@"1"]];

you should see the crash that you're expecting because the first item in the array will be not be a string constant, but rather a regular old dynamically allocated string subject to the usual reference counting rules.

How Objective-C handles the memory of immutable strings

From Is a literal NSString autoreleased or does it need to be released?

Compiler allocated strings (of the format @"STRING") are constant, and
so -retain, -release, and -autorelease messages to them are ignored.
You don't have to release or autorelease foo in this case (but it
won't hurt).

Under the hood when you do

NSString* yourString = @"ABC";

the string will be stored in a area of memory called data segment. This area never changes after the application is launched. Here strings are treated as constants for your app. At the same time a string is an object, so if you want to keep it you call retain or copy.

On the contary when you do

NSString* yourString = // alloc-init

you create an object on the heap. If you forget to release you have a memory leak. If someone else destroy it, and you try to access it, you have a bad access to that memory location.

Hope that helps.

Why retainCount returns 2

+1 because you alloc/init'd it

+1 because self.myvar retains it (as set out in your property declaration)

if you autorelease after alloc/init, it will go back down to 1... then if you set self.myvar to nil, it will hit 0 (if nothing else has retained it in the meantime)

But as vikingosegundo has said, you don't want to be messing with retain counts. The OS determines when to knock them back down, so you can't use them as a reliable measure of state.



Related Topics



Leave a reply



Submit