Reputation: 274
I have an NSString
object that I've allocated. I want to append to this string occasionally throughout the lifetime of the app
I am confused about how to properly handle the memory in the example below. Thanks.
stringByAppendingString:
returns?my_string
each time I do an append?Code:
NSString* my_string = [[NSString alloc] initWithString:@"Initial string"];
NSString* something = [NSString stringWithFormat:@"%@", @" with something"];
my_string = [[my_string stringByAppendingString:something] retain];
NSString* something_else = [NSString stringWithFormat:@"%@", @" and something_else"];
my_string = [[my_string stringByAppendingString:something_else] retain];
[my_string release];
Upvotes: 0
Views: 1689
Reputation: 18657
The primary thing to keep in mind is that NSString
is immutable. Whether you alloc, create with format, or append, you're always getting a new string object returned. So let's break this down:
NSString* my_string = [[NSString alloc] initWithString:@"Initial string"];
//String object created with "Initial string" content. Retain +1
NSString* something = [NSString stringWithFormat:@"%@", @" with something"];
//String object created with content " with something" and autoreleased.
my_string = [[my_string stringByAppendingString:something] retain];
//String object created with content "Initial string with something", autorelesed, and retained. Effective retain +1
//Assignment replaces old "Initial string" reference. "Initial string" object still has retain of +1, so it doesn't get deallocated (it leaks).
NSString* something_else = [NSString stringWithFormat:@"%@", @" and something_else"];
//String object created with content " and something_else" and autoreleased.
my_string = [[my_string stringByAppendingString:something_else] retain];
//String object created with contents "Initial string with something and something_else", autoreleaased, and retained. Effective retain +1
//Assignment replaces old "Initial string with something" reference. "initial string with something" object still had a retain of +1, so the object leaks.
[my_string release];
//String object "Initial string with something and something_else" released. Retain -1. Object is deallocated and doesn't leak.
//...Sometime later at the end of the runloop, the autorelease pool is drained and " with something" and " with something_else" are both deallocated.
So:
Yes. It's ok to append an autoreleased string. release
is not called on an autoreleased object until the end of the run loop, which, at the very least, is after this method exits.
Yes, you are leaking the objects that were previously assigned to my_string
each time you do an append... but it's not the append that's causing the leak, it's the assignment. You could assign nil
to my_string
and the retained object my_string
used to point to would still leak if you didn't release
or autorelease
it first.
Upvotes: 1
Reputation: 16827
NSString* my_string = [[NSString alloc] initWithString:@"Initial string"];
is not autoreleased (as it is created with an init... method, this is a convention), it has a retainCount of 1.
NSString* something = [NSString stringWithFormat:@"%@", @" with something"];
is autoreleased.
is it OK to append with a string that belongs to the autorelease pool, as stringByAppendingString: returns
As long as you would expect it to live for yes. However in your code:
NSString* my_string = [[NSString alloc] initWithString:@"Initial string"];
NSString* something = [NSString stringWithFormat:@"%@", @" with something"];
my_string = [[my_string stringByAppendingString:something] retain];
you have a leak. You should autorelease my_string before re-assigning it. So the last line should be:
my_string = [[[my_string autorelease] stringByAppendingString:something] retain];
otherwise you have forever lost the pointer to the object you are meant to have released. As you retain the result, you are responsible for releasing it so you also have a leak in the line before last which should be
my_string = [[[my_string autorelease] stringByAppendingString:something_else] retain];
Upvotes: 3
Reputation: 1118
In the 2nd assignment you're losing the retained reference of the first stringByAppendingString
call, so:
stringByAppendingString
returns a new autoreleased string. Don't retain it if you're using the value temporarily.Upvotes: 0