views:

156

answers:

3

This is probably a question that is more about object alloc/retain/release, but I'll use NSString as an example. I'm aware that I can do:

NSString* myString = [[NSString alloc] initWithString:@"Test"];

to essentially allocate and initialize a string referenced by my variable myString which I should later call [myString release] upon. However, if after I do this, I set it to some other string such as:

myString = someOtherString;

does that essentially create a memory leak because I've reassigned my pointer to another object and lost all reference to the original one I allocated?

If I simply want to personally allocate and release a string and then change its value at various times, should I be using a different syntax other than '=' or is that overloaded to properly change the contents of the object that is originally represented by myString when I use =.

+1  A: 

If you relinquished ownership properly before assigning another pointer value to it, there is no leak:

NSString *a = [[NSString alloc] init];
// ... 
[a release]; // relinquish ownership
a = someOtherString; // fine, we don't own the previous instance anymore

The moment you relinquish ownership of an object by calling release, you should consider it effectively deallocated - this might have been the last reference to it. That the pointer still has the same value is just a side-effect of how Objective-C class types are implemented and used.

Depending on memory constraints and what your code does, you could also use autoreleased instances:

NSString *a = [NSString stringWithString:@"moo"];
a = someOtherString; // fine, a will be released later by the nearest autorelease pool

Note that if the reference isn't a local variable but an ivar, you'll probably want to use declared properties instead.

Georg Fritzsche
+3  A: 

Yes, in your example you are leaking the memory.

NSString* myString = [[NSString alloc] initWithString:@"Test"];
myString = someOtherString;

You this should be done like so:

NSString* myString = [[NSString alloc] initWithString:@"Test"];
[myString release];
myString = someOtherString;

The best way I have heard the whole retain/release thing described is imagine you are walking a dog for someone. Your "object" is a dog and "retain" puts a leash on the dog and "release" takes a leash off. You can have as many leashes on the dog as you want but you want to keep at least one leash on the dog so he doesn't run free (leak) and you want to take all the leashes off the dog once you get it back to the owner (you want to get rid of the object). In your example, you can think of it as letting go of the leash on the dog mid-walk and picking up the leash of a different dog.

ACBurk
Right, and the memory leak is like your dog walking clients drying up as word gets around that you keep losing people's dogs.
jasongetsdown
I think your analogy falls a little short because if a "leash" is like a reference count and a dog only 'runs away' if it has no leashes attached to its collar, then my example would not so much be picking up the leash of a different dog so much as letting go of my leash and turning to watch another dog. Sounds like a more correct analogy would be to not have owners holding leashes so much as adding a leash that connects to a lamppost or removing them etc. But thanks for that clarification. :)
Joey
A: 

You could do the following:

NSString *myString = [NSString stringWithString:@"Test"];

The returned string is autoreleased so you don't have to release it. You also don't "own" it. If that's an issue do as other's have suggested and send a release message to myString before you reassign it's value.

jasongetsdown