I have a comprehension question. This method is given:
- (NSArray*)test {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
NSString *result = [[NSString alloc] initWithBytes:[data bytes]
length:[data length]
encoding:NSMacOSRomanStringEncoding];
result = [result stringByAppendingString:@"something"];
NSArray *arr = [NSArray arrayWithObject:result];
//[result release];
return arr;
}
If I uncomment the release
the App would crash and say it cannot access a released object.
By not release
ing the result
string Instruments would report a leak (NSPlaceholderString).
I can autorelease
it on the same line I alloc
it, that would solve the problem (which I'm currently doing in my App).
If I understand it correctly stringByAppendingString:
should create an autoreleased object so the 'old' result could be deallocated. Then the method arrayWithObject:
should copy
the object into an array. So my thought was to release the string after it was copied to the array.
Am I missing something or something wrong with my knowledge?
Let's go through your code line by line.
- (NSArray*)test {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
This creates a data object. You don't own it, but it will stick around for the rest of the method's time. So far, so good.
NSString *result = [[NSString alloc] initWithBytes:[data bytes]
length:[data length]
encoding:NSMacOSRomanStringEncoding];
This creates a string object that you own. Again, no problem here — we just need to release it later.
result = [result stringByAppendingString:@"something"];
You throw away your reference to the string object that was in result
and store a new string object that you do not own. This is a leak because you can no longer release the original string. Also, you're correct in noting that the new string can be treated as an autoreleased object — which means you should not release it.
NSArray *arr = [NSArray arrayWithObject:result];
Contrary to your belief, this does not copy anything. It merely keeps a reference to the new string and retains it.
//[result release];
You should not release result
at this point, because the object it contains is not one you own — you got it from stringByAppendingString:
, not from a method with new
, alloc
, retain
or copy
in its name. Releasing this object that you do not own will almost certainly result in a crash at some point. The old object that you own and should release was lost two lines earlier, and releasing something else in its place won't help.
result = [result stringByAppendingString:@"something"];
This line replaces the first allocated string by a new autoreleased string.
So the first string is leaked and the second one should not be released. This explains why uncommenting the release line crashes.