ios: Retain count of 2147483647? [duplicate] - ios

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
NSString retainCount is 2147483647
Objective C NSString* property retain count oddity
Have a look at the following code:
NSString* testString = [[NSString alloc] initWithString:#"Test"];
NSLog(#"[testString retainCount] = %d", [testString retainCount] );
NSMutableArray* ma = [[NSMutableArray alloc] init];
[ma insertObject:testString atIndex:0];
[testString release];
NSLog(#"%#", [ma objectAtIndex:0]);
This is the output on the console :
[testString retainCount] = 2147483647
Test
How can this happen? I expected 1 not 2147483647!

You initiate your NSString object with string literal and 2 following things happen:
As NSString is immutable -initWithString: method optimizes string creation so that your testString actually points to a same string you create it with (#"Test")
#"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

You can only have two expectations for the result of retainCount:
1) It's greater than 1. You cannot predict what number it will actually be because you don't know who else is using it. You don't know how somebody else is using it. It's not a number you should care about.
2) People will tell you not to use it. Because you shouldn't. Use the rules to balance your retains and releases. Do not use retainCount. It will frustrate and confuse you, for no value.

Related

Are all objects in the iOS automatically added to the auto release pool?

Are all objects in the iOS automatically added to the autorelease pool?When ARC? If no, which one will be added & which one not?
eg:
{
NSString *str = [[NSString alloc] init];
NSString *str2 = [NSString string];
}
+ (NSString *)string {
return [[NSString alloc] init];
}
str2 will be added to autorelease pool because it creates by a method that name as 'copy/mutableCopy/alloc/new'. So it does not create by self. But I don't know is str will be added or not and why?
ARC makes no guarantees as to what objects are added to the autorelease pool and what objects are not. It is very possible that neither of the objects in your example are ever added to the autorelease pool under ARC.
The answer is NO. In fact, which will be added auto release pool is obj of method "string".
// ARC
{
NSString __strong *str = [[NSString alloc] init]; // STEP A
NSString __strong *str2 = [NSString string]; // STEP B
}// STEP Finish
+ (NSString *)string {
id obj = [[NSString alloc] init];
return obj;
}
Like this may help you understand.In ARC, object has __strong modifier(default).Because a object must has a strong pointer point to it, or it die.
STEP A : str create a NSString object and strong point to itself.
STEP B : str2 not create but strong point to a object which is obj.obj created by NSString in method string, because it needs return, so added to auto release pool. And str2 strong point to obj, so obj can't release by auto release pool, there still a strong pointer point to it.
STEP Finish,str,str2 out of method, no more strong pointer .So they had release.
At STEP B, why will needs auto release pool? Because if don't put obj into auto release pool, it will release by compiler, just like str in the STEP Finish.
All this from the book "Pro multithreading and memory management for iOS and OS X".
Forget my poor English.

Multiple NSString declaration and initialization

I am new to the ios development.I was checking the NSString and where I had found out that it was excessed using the multiple ways which is as under
1) NSString *theString = #"hello";
2) NSString *string1 = [NSString stringWithString:#"This is"];
3) NSString *string =[[NSString alloc]init];
string =#"Hello";
Now I am confused with above three and would like to know the differences between then?
Yes all three are ways to create string...I try to explain you one by one.
One think you must remember that in Objective-c string is represented by #"".
whatever comes double quotes is string eg #"Hello" is string. #"" is basically literal to create NSString.
NSString *theString = #"hello";
EDIT:
In this statement we are creating an NSString constant. Objective-C string constant is created at compile time and exists throughout your program’s execution.
2. NSString *string1 = [NSString stringWithString:#"This is"];
In this statement again, we are creating an autorelease object of NSString, but here a slide diff. than the first case. here we are using another NSString object to create a new autorelease object of NSString. So generally we use stringWithString method when we already have NSString Object and we want another NSString object with similar content.
3. NSString *string =[[NSString alloc]init];
string =#"Hello";
Here, In first statement you are creating a NSString Object that you owned and it is your responsibility to release it (In non-ARC code), once you done with this object.
Second statement is similar to case 1, by string literal you are creating string Object.
but when you put these two statements together it causes you memory-leak(In non-ARC code), because in statement one you are allocating & initiating memory for new string object and right after in second statement you are again assigning a new string object to the same string reference.
1) and 2) is the same. there is no difference. [NSString stringWithString: str] just does nothing and returns str if str is immutable already. via this link
3) you create empty NSString pointer. after you assign this string with ' = ' is same way with 1) and it alloc memory to your NSString. You can watch this NSString pointer in 3) and you see pointer was changed:
NSString *string =[[NSString alloc]init];
printf("\n string_1-> = %p\n", string );
string = #"Hello";
printf("\n string_2-> = %p\n", string );
OK, first off, the syntax #"blah" is an Objective-C literal to create an NSString. Essentially it is an NSString.
Also, there are two parts to each statement. The declaration of the string variable NSString *string and the instantiation string = <something>.
So...
This is how you would do it most of the time. You declare the variable and set it using the objective-c literal.
This adds a bit of redundancy and you wouldn't really use it like this. You'd maybe use it with a substring or something from another string. As it is you are essentially creating two objects here. The first is [NSString stringWithString:<>]; and the second is #"This is".
This is a bit odd. You are first creating an empty string #"" and then you are replacing this string with #"Hello". Don't do this. There is no point. You may as well just do number 1 as the result is the same.
All three will work but in these exact cases you'd be better off using the first.

A bug with NSMutableArray of NSString?

NSString *str = #"1 2 3 4 5";
NSMutableArray *strArray = [[[str componentsSeparatedByString:#" "] mutableCopy] autorelease];
[strArray removeObjectAtIndex:3];
[strArray removeObjectAtIndex:0];
At the end of this code I expect that array contains #"2", #"3", #"5".
But it contains 0x00000, #"2", #"3".
How to fix it? Numbers are for example only, there could be various strings of various length separated with spaces.
UPDATED
It is strange, but it really writes 2, 3, 5 into console.
But here is the same array in debug window:
Not sure why your code is not working its working fine for me, also tried the same in other way below :-
NSString *str = #"1 2 3 4 5";
NSArray *arr1= [str componentsSeparatedByString:#" "];
NSMutableArray *strArray=[NSMutableArray arrayWithArray:arr1];
[strArray removeObjectAtIndex:3];
[strArray removeObjectAtIndex:0];
NSLog(#"%#",strArray);
Output:-
2
3
5
Here is what I think is happening. What you have is, if anything, a bug in the debugger.
Let's assume for the moment that NSMutableArray is represented by a normal C array internally. The naive implementation of -removeObjectAtIndex: would shuffle up all the objects after the one you want to remove into the previous slot in the array. This has O(n) complexity, where n is the number of objects in the array.
An optimisation might be to associate a "base index" with the array which will be subtracted from the index supplied to any method that takes an index as a parameter. That way, [foo removeObjectAtIndex: 0] can be implemented by simply assigning nil to the first element and bumping the base index for constant time complexity.
I'm sure the real implementation is more complex than that, but the above just serves to illustrate the idea.
If the debugger doesn't know about this, it would display the underlying C array exactly as it does in the screen cap your question. The point is that you can't really trust the debugger on anything where it can't be expected to know the internals of the object. Printing the description to the console is a much more reliable method of examining the object - as long as -description has a helpful implementation.
Why aren't you using ARC? I have tested that code using ARC and it works. So, can you explain it a little bit more what you are trying to do? (I could't added it as comment)
remove your autorelease! Fine working for me!
NSString *str = #"1 2 3 4 5";
NSMutableArray *strArray = [[str componentsSeparatedByString:#" "] mutableCopy];
[strArray removeObjectAtIndex:3];
[strArray removeObjectAtIndex:0];
NSLog(#"strArray = %#", strArray);
2013-10-16 14:29:35.537 Notes[566:c07] strArray = (
2,
3,
5
)

multiple assignments of objects to variable under ARC

There's a point of memory management I'm not 100% clear on, suppose there is the following code:
{
NSString *string = [[NSString alloc] init];
string = [[NSString alloc] init];
}
Does this cause a memory leak of the first allocation? If not why not?
Under ARC, this does not leak memory. This is because any time a strong object pointer is changed, the compiler automatically sends a release to the old object. Local variables, like NSString *string, are strong by default.
So your code above gets compiled to something more like this:
{
NSString *string = [[NSString alloc] init];
// Oh, we're changing what `string` points to. Gotta release the old value.
[string release];
string = [[NSString alloc] init];
}
Conceptually, BJ is correct, but the generated code is slightly different. It goes something like this:
NSString *string = [[NSString alloc] init];
// Oh, we're changing what `string` points to. Gotta release the old value.
NSString *tmpString = string;
string = [[NSString alloc] init];
[tmpString release];
[string release]; // string goes out of scope at this point in your code
This order of operation is usually not that critical (and if you care too much about it, you are probably coding incorrectly). But understanding it explains why the objects are destroyed exactly when they are.
No it does not cause a leak. ARC will release the first string before it sets the second string. This is the truly amazing power of ARC!

Over-release an object and the app does not crash

#property (retain) NSString *testString;
self.testString = [[NSString alloc] initWithString:#"aaa"];
[self.testString retain];
self.testString = [NSString stringWithString:#"a"];
[self.testString release];
[self.testString release];
Let's go line by line:
Line 2: retain count of testString = 2
Line 3: retain count of testString = 3
Line 4: retain count of testString = 1
Line 5: retain count of testString = 0
Line 6: it should crash
Even if there's other stuff holding to testString in CoreFoundation, it eventually will go away. But the app never crash due to this.
Anyone could explain this? Thanks!
see this code and its log:
NSString *string1 = [NSString stringWithString:#"a"];
NSString *string2= #"a";
NSLog(#"String1: %p", string1);
NSLog(#"String2: %p", string2);
2012-03-22 13:21:49.433 TableDemo[37385:f803] String1: 0x5860
2012-03-22 13:21:49.434 TableDemo[37385:f803] String2: 0x5860
as you see [NSString stringWithString:#"a"]; doesn't create a new string, it uses the string literal #"a". And string literals can't be deallocated.
Try your code with NSMutableString and you will see a crash.
I am not an expert about this, so please take this with a grain of salt. I guess that [NSString stringWithString:#"a"] will probably just return the literal string #"a", i.e. it just returns its argument. As #"a" is a literal, it probably resides in constant memory and can't be deallocated (so it should be initialized with a very high retain count).
[NSString stringWithString:#"a"] returns an autoreleased object. That means "the true" retain count is 2 not 1 in line 4. In line 6 you are overreleasing your variable but the crash will happen later - on the autorelease pool drain.

Resources