I was going through the memory management concepts. I created one string1
and assign that string1
into another string2
, now I release this string1
.
Here string2
retain count is 1 but on NSLog
statement it gives EXC Bad access.
When I am assigning the string
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"];
string2 = string1;
NSLog(@"string1 memory address = %p, string2 memory address = %p", &string1, &string2);
[string1 release];
NSLog(@"[string2 retainCount] = %lu", (unsigned long)[string2 retainCount]);
NSLog(@"string2 = %@", string2); // here app is crashing
Does it means that string2 has an autorelease message also with it because if I do string2 = [string1 copy];
instead of string2 = string1;
it doesn't crash.
So I wanted to ask whether the crash is because it has autorelease message of string2
and how it is relating with string2
release command.
Please advice!
Assignment doesn't change object's retain count if you use manual memory management in Objective-C. And you for sure use it, otherwise, you can't invoke release
method in your code.
So, your code does the following. It creates NSString
object with retain count = 1, and assigns it to string1
pointer. After that, you assigns string1
to string2
. Now you have 2 pointers to the same object, and retain count of this object is still 1. Then you release object, it deallocated immediately. And after that you experiencing crash:
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"]; // string retain count is 1
string2 = string1; // 2 pointers to same string, retain count is still 1
[string1 release]; // string is deallocated when retain count drops to 0
NSLog(@"string2 = %@", string2); // here app is crashing
To fix that, you can use retain
when you do an assignment.
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"]; // string retain count is 1
string2 = [string1 retain]; // 2 pointers to same string, retain count is 2
[string1 release]; // string retain count back to 1
NSLog(@"string2 = %@", string2); // no crash
Also, you can use copy
. Note that for NSString
copy doesn't actually copies an object, it simply invokes retain
. There is no need to perform actual copying, because NSString
is immutable and can't be changed. If we will use NSMutableString
, things will change:
NSMutableString * string1 = [[NSMutableString alloc]initWithFormat:@"hello"]; // string retain count is 1
NSMutableString * string2 = [string1 copy]; // 2 separate strings, both have retain count 1
[string1 release]; // string1 is deallocated
NSLog(@"string2 = %@", string2); // no crash, string2 retain count is 1
Alternatively, you can use ARC. It will insert corresponding retain/release calls at compile time. Code then will look like:
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"];
string2 = string1;
string1 = nil;
NSLog(@"string2 = %@", string2); // no crash
I suggest to understand manual memory management first, and after that migrate to ARC.