Differences between NSStrings? - objective-c

I understand that the v03 example creates an object that I own and must ultimately release. What I would like to know is are there any differences between the first two(v_01 & v02), or are they essentially the same?
// Version_01
userName = #"Teddy";
// Version_02
userName = [NSString stringWithString:#"Gary"];
// Version_03
userName = [[NSString alloc] initWithString:#"Caroline"];
... some code
[userName release];
gary

They are all similar, but there are some slight differences between the three.
The first one is a pointer to a string constant. The string Teddy is stored in read-only memory, and userName is a pointer to this string constant. You need not (and cannot) retain or release this object, since it exists "permanently" (that is, for the duration of the program).
The second one is an autoreleased string object with the contents Gary. When returned to you, it has a release count of 0. It may be retained and released as needed.
The third one is similar to the second one, but it is not autoreleased, so it has a retain count of 1 when it is initially returned to you. Like the second one, it may be retained and released as needed.

Most of the differences in these instances is how the memory is managed. If you want a clearer view of what's happening in the background, you might want to peruse the Objective-C Memory Management Guide.
// Version_01
userName = #"Teddy";
This is a String constant that does not have any memory management associated with it. The memory used to hold the value is part of the memory in which the code resides in (essentially). retain and release calls on the variable will be ignored.
// Version_02
userName = [NSString stringWithString:#"Gary"];
This is an autoreleased instance of an NSString object. Its retain count is currently one and will be released by the autorelease pool soon unless it is retained.
// Version_03
userName = [[NSString alloc] initWithString:#"Caroline"];
[userName release];
This is a managed instance of an NSString. When it is first initialized, its retain count is one. After releasing it, the retain count went down to zero, therefore, its memory will be deallocated. Referring to the variable userName after releasing it will cause an EXE_BAD_ACCESS error.

The first two or essentially the same
The latter one is not however as userName would be an invalid string object at that point.
However changing it to
userName = [[[NSString alloc] initWithString:#"Caroline"] autorelease];
would render it effectively the same as the previous two.

version 01: is a string constant....
version 02: is an auto-released NSString created by copying a constant.

Practically, there are no differences, as long as you don't attempt to use the Version_03 string after you release it. If you want to do that, you'll need to autorelease it instead.

Related

Returning NSArray element

In MRC code returning NSArray element like this:
NSString* MyName()
{
NSArray *names = [NSArray arrayWithArray:[[NSHost currentHost] names]];
return [names objectAtIndex:0];
}
void BullCrap()
{
NSString *wouldItBeRetainedAutomatically = MyName();
}
wouldItBeRetainedAutomatically in BullCrap() scope? I am assuming I don't need to send wouldItBeRetainedAutomatically retain message to make sure it is still available after names in MyName() is deallocated? Or names wouldn't be deallocated until BullCrap() is done?
NOTE: I know I should use ARC, but i can't.
In order to be completely sure the answer to this question is correct it would be necessary to see where listOfNames comes from. This will tell us what memory management contract has been made between the system framework and your calling code.
With that said, it is probably safe to say that the system framework has autoreleased the NSArray that was returned and stored in listOfNames. So listOfNames will get released and disappear as soon as the autorelease pool is flushed. You create the name array using arrayWithArray which will also return an autoreleased instance.
However, you are specifically asking about the memory management "state" of the first element of listOfNames (or names) that is returned by the MyName function. This has almost certainly only been retained by the listOfNames array (and the names array). (Again the caveat above still stands). Given that listOfNames (and names) will get autoreleased shortly, the elements of the array will also get released.
Therefore, you should probably return the element from MyName with a call to autorelease and then retain wouldItBeRetainedAutomatically in BullCrap if you need it to stick around. There is nothing in the code that you've shown that would suggest it will be retained automatically for you.
On a side note, the names array that you create is unnecessary in the example you give. The same could be achieved as follows:
NSString* MyName()
{
//listOfNames is returned by SystemFramework API
return [listOfNames objectAtIndex:0];
}
Using the intermediate names array simply confuses the matter.
In this case it looks like you shouldn't do anything, simply because you say listOfNames is returned by a system API and this method is (in a very contrived way) adding it to and then removing it from an array which will be destroyed. So, the array temporarily retains the listOfNames but doesn't really change anything and the listOfNames is (depending on how it was really created) already auto released.
Obviously there's a massive caveat on where listOfNames actually comes from...

Best allocation for NSString when alternating between constant and non constant strings

I would like some help better understanding the memory characteristics of Strings in Cocoa.
The app I am working with uses one view controller and n tool objects. The View controller lives for the life of the program but the tool objects are allocated and released.
Suppose I have a string toolName_ and in my implementation I configure the incoming tool object: if the object does not have a tool name, I want to set the toolName_ string to #"not set". If the tool has a name I want to set the string to the name of the tool.
I would like to know the proper way to store the incoming value into the toolName_ given that sometimes this will be an allocated object and sometimes this will be a constant string.
-(BOOL)setToolObject: ToolObject: obj{
ToolObject someObj = nil;
someObj = [[ToolObject alloc]initWithObject obj];
if(someObj != nil){
if(! [someObj.toolName isEqualToString: #""]){
self->toolName_ = Which method should I use given the above question?
The last instance may have been a constant string but may not have.
[self->toolName_ release] (can I send a release message to a constant
string without causing a problem?)
self->toolName = [[NSString alloc]initWithString:someObj.toolName];
OR
self->tool name = [NSString stringWithString: someObj.toolName];
This method is self releasing but I don't own it and I'm still not sure
what happens to the constant string if it existed. I think I read it's
not recommended to use this on member vars.
}else{
self->toolName_ = #"not set";
}
return YES;
}else{
return NO;
}
}
Advice appreciated.
I highly suggest to (possibly) use ARC, and if you can't use it (or maybe you just want to understand how memory management works?), to don't send retain and release messages from outside the class. Instead you should do this in the accessors.
So you should create a retain or copy property (usually with immutable strings is preferable to use copy, because they may be assigned to mutable strings, so making invalid the assumption that you are working with an immutable - thus thread safe - property).
So in your case I suggest a setter like this one:
- (void) setToolName: (NSString*) toolName
{
if(_toolName== toolName)
return;
[_toolName release];
_toolName= [toolName copy];
}
This way you're doing it fine, you shouldn't be concerned about what is the retain count of the setter argument. In case it is a string literal which has an unknown retain count, the object does not even respond to a release message, so it will stay alive for all the program (unlike it seems it is efficient because it avoids the overhead of creating an object at runtime). If you copy an immutable object (unless it something like a cached NSNumber, or a string literal), the code just does a simple assignment and the retain count gets increased.
So if you just follow the rule of "I retain (or copy) what I need to use, I release what I don't need to use anymore", you're doing it fine and you shouldn't worry about what happens in particular case like with string literals.

iOS memory management about NSString

Is there any different between
NSString * str = #"123";
and
NSString * str = [[NSString alloc] initWithString:#"123"];
from compiler's aspect?
Theoretically yes; in implementation detail, probably not.
In the first case, the compiler creates a constant string and assigns a pointer to it to the variable str. You do not own the string.
In the second case, the compiler creates a constant string (as before) but this time it is used by the run time as a parameter in initialising another string that you do own (because the second string was created using alloc).
That's the end of the stuff you need to know.
However, there is a lot of optimisation that goes on. Because NSStrings are immutable, you'll find that initWithString: actually just returns the parameter. Normally, it would retain the parameter before returning it to you (because you are expecting to own it) but literal strings have a special retainCount (INT_MAX I think) to stop the run time from ever trying to deallocate them. So in practice, your second line of code produces identical results to the first.
This incidentally, is why it is incorrect top say the string is autoreleased in the first case, because it isn't. It's just a constant string with a special retain count.
But you can and should safely ignore the implementation detail and just remember, you don't own the string in the first case, but you do own it in the second case.
Lots of differences. The most important is that you own the second string so you're responsible for releasing it (as is the case whenever you get an object from the init family of methods).
Another is that the former creates a string literal, and if you make a new string with the same literal, they will be pointers to the same object. If you do this:
NSString * str1 = #"123";
NSString * str2 = [[NSString alloc] initWithString:#"123"];
NSString * str3 = #"123";
Then str1 == str2 is false, but str1 == str3 is true. (Of course, the string content is the same, so isEqual: will return true. Also, while this does make for faster comparison, you probably shouldn't use it because it's an implementation detail and could in theory change in the future).
Yes, in the first case you do not own the string and you are not responsible to release it.
In the second case, instead, you are calling alloc thus you become the owner of the object and you must call release on it when you have done, otherwise it will become a memory leak.
In general, if the method you use to get your object contains "new","alloc","copy" or "mutableCopy" then you are the owner of the object and you are responsible to release it.
Check the memory management rules
Yes. The first is assignment of an NSString, and in the second the alloc (which means you need to release it in some way later) and initWithString: method are getting called.
Yes , first statement creates an autorelease object.
Second one creates an object occupying some memory and you have to release it after using it.
The main important difference about memory (your question title) is:
when you do:
NSString* myString = #"my text";
you are allocating an object of NSConstantString type.
The difference with NSString is:
NSConstantString is statically allocate, while NSString is dynamically allocated.

Retain/release of returned objects

I am new to Objective-C, so this might be a dumb question.
I cannot help but see the similarities between ObjC and Microsoft's COM with respect to memory management (AddRef/Release vs retain/release). In a COM environment, it's more or less imposed on you to always AddRef (retain) an object before returning it to the caller. From what I've seen so far (I'm a third through Cocoa® Programming for Mac® OS X (3rd Edition)), the memory management part is somewhat fuzzy.
Assuming there is no GC, what is the idiomatic way to return an object?
Read Memory Management Programming Guide about autorelease pools.
In Objective-C, by convention, objects should be returned autoreleased (unless the method returning the object has a name that begins with “alloc”, “new”, “copy”, or “mutableCopy”). Autoreleased objects are tracked by Objective-C in a pool and automatically handled, which means you don't need to care about sending a final release to them. This greatly simplifies reference counting compared to COM, and this is why you're not seeing any release calls on returned objects most of the time. In contrast, the same convention specifies that all objects returned by a method whose name begins with alloc, new, copy, or mutableCopy, are the responsibility of the method caller. You have to manually call release on these objects or your program will have memory leaks.
Cocoa goes around the limitations of AddRef/Release in COM by introducing a third sibling; autorelease.
retain - I need this, make it stick around.
release - I don't need this anymore, you may remove it immediately.
autorelease - I don't need this, but let it stay around a few seconds in case someone else wants to pick it up first.
This tiny addition allow most return values to be handles as-if we had garbage collection. If you are not interested in keeping the return value around, just do nothing extra.
In order to get this to work there is a convention (a convention good enough to let the compiler do the memory stuff automatically for you with upcoming ARC):
Method names beginning with these must return retained instances:
alloc
copy
new
retain
All other must return autoreleased instances.
Three example implementation for how this can be applied in practice:
-(NSString*)newHelloWorldString {
NSString* s = [NSString stringWithString:#"Hello world"];
// Apply retain because s in now autoreleased
return [s retain];
}
-(NSString*)helloWorldString {
NSString* s = [[NSString alloc] initWithString:#"Hello world"];
// Apply autorelease because s is now retained.
return [s autorelease];
}
-(NSString*)fullName {
// No memory management needed, everything is autoreleased and good.
NSString* fn = [self firstName];
NSString* ln = [self lastName];
NSString* s = [NSString stringWithFormat:#"%# %#", fn, ln];
return s;
}
Generally something like
return [object autorelease];
and you can retain on the other end.
If you are planning to deploy on Lion/iOS5 or are using the latest SDK then also check out ARC.
Essentially i would recommend making the class that receives it retain it. i.e class stackoverflow receives object answer.
i.e
-(void) setAnswer:(Answer*) _answer{
self.answer = _answer; // If the answer is created from a returned message.
[_answer release];
}
edit: I think I might have put up the wrong stuff up there now that i am looking at it the 2nd time . Meant something along the lines:
Answer *_answer = [stackoverflow createAnswer];
self.answer = _answer;
[_answer release];
If you return an object , it is up to the owner to retain it , i would avoid autoreleases wherever possible because once the nspool kicks in, those objects are gone and if they are still used, it will cause problems.
i.e Answer *answer = [stackoverflow getAnswer] and if answer was created in the getanswer method then whomever is retrieving it is responsible in releasing it.
Makes sense?

Does this Objective-C code leak memory?

One thing I'm concerned about is I create two ints, but don't release them. Would it be better to make them NSIntegers?
-(void) flipCoin {
int heads = [headsLabel.text intValue];
int tails = [tailsLabel.text intValue];
if (random() %2 ==1 )
{
heads++;
}
else {
tails++;
}
headsLabel.text = [NSString stringWithFormat:#"%d", heads] ;
tailsLabel.text = [NSString stringWithFormat:#"%d", tails];
}
As sha notes, local variables get allocated in the current stack frame. As soon as the current function call returns, the stack gets "popped", and the memory occupied for the current call is not released so much as abandoned, until it is overwritten by the next call that gets pushed into that part of the stack.
So why do we have to release variables like this:
MyClass *myObject = [[MyClass alloc] init];
Well, you actually don't have to worry about "myObject". It's on the stack, just like your ints, and it will get cleaned up when the current call finishes.
What you have to worry about is the memory that myObject—which is a pointer—points to. It's off somewhere on the heap. Constructing an object involves asking the runtime for some semi-permanent place to put it; that process returns a memory address, which your pointer stores.
alloc and release are Objective-C idioms that largely replace C's malloc() and free() functions, but all of them ultimately are asking the computer to set aside memory on the heap, and all of that memory must ultimately be returned, either through an autorelease pool, a release message, or a free() call.
int is what is known as a primitive type. It is not a pointer to an Objective-C object so you cannot release it. You can't even send a message to it.
NSInteger is also a primitive type in the sense that it is a typedef to a primitive type (long usually). So you can't release that either.
What do you need to release? You need to release any object you obtained by sending new, alloc or a method containing copy. You also need to release objects to which you have sent retain. So all of the local variables in the following must be released:
-(void) foo
{
NSString* aString = [[NSString alloc] init];
NSString* aString2 = [aString copy];
NSString* aString3 = [someOtherString retain];
NSString* aString4 = [#"some string" copy];
}
NB due to implementation details, you would actually get away with not releasing the aString4 but you don't need to worry about it.
No. Your heads and tails variables are local and stored on the stack. This won't cause a leak. Your two NSString assignments near the bottom are created using convenience constructors and will be autoreleased for you.
All default datatypes (int, char, BOOL, etc) are automatically managed for you, and do not (and cannot) be released (for all intents and purposes).
NSIntegers behave likewise, as they are just signed ints (or signed longs on 64-bit machines).
Objects you initialize, however, like NSString or NSArray will usually have to be released (unless they are autoreleased, like the NSStrings at the bottom of your code). If you ever call -alloc and -init on something, you will have to later release it. If you ever doubt whether a method returns an autoreleased object, just read the documentation (it will tell you).
Also, if you want to read up on memory management, there are plenty of wonderful sources that will teach you (Google is a great place to start!), and if you ever think that your code leaks memory, run it through Instruments, and you'll be able to tell...