1

I have a global NSString variable declared in a .m file. When I use the stringWithFormat to give it a string value anywhere within the .m file, that value does not persist in between function calls. However when I do the same using stringWithString, the value persists throughout the implementation and any functions calls thus giving it a true global behavior. Rather to put it differently, how does the memory management differ internally for stringWithFormat vs stringWithString?

Why does the value persist for stringWithString while throwing a "message sent to deallocated instance" (on subsequent use of the NSString say in a NSLog statement in another function which comes after a function that gave the NSString a value using stringWithFormat) when using stringWithFormat? No such issues when I replace the same with stringWithString.

Thanks!

EDIT: I forgot to mention that YES it worked in case of stringWithFormat when I did a manual retain afterward. The value persisted. Hence the question.

2
  • Please, paste some code. Commented Feb 22, 2011 at 12:00
  • Its a theoretical question. I see two situations with a NSString and I just want to know what the difference is between stringWithFormat and stringWithString Commented Feb 22, 2011 at 12:05

2 Answers 2

3

It sounds like you aren't retaining the string and because of this when you try to access it later on it has been deallocated. If you aren't familiar with memory management, take a look at the Memory Management Programming Guide from Apple.

The reason -stringWithString: doesn't break is likely because the compiler is doing some optimisation with string literals; It looks through the program and stores just one reference to identical strings that are defined. Because of this your pointer will remain valid throughout the lifetime of the app.

You should not rely on this. You cannot guarantee that all compilers will do this optimisation. Retain the variable when you make it and release it when you stop needing it.

Sign up to request clarification or add additional context in comments.

3 Comments

Edited the post. I did figure out that much. After giving the string a value using stringWithFormat, I did perform a retain on it and there are no issues. While stringWithString needs no such actions to be taken. Hence the question as to how they are handled internally w.r.t memory. Thanks for the reply.
As far as I read everywhere, both stringWithString and stringWithFormat return autoreleased pointers.
It is not to do with what is returned but is to do with how the internals of the compiler work. fluchtpunkt shows this nicely in his edit.
2

the compiler is smart, and instead of creating dozens of different NSString instances that all hold the same value he creates one instance that can't be released and all the other instances just point to the NSString that is hardcoded in your program.

And because the hardcoded NSString gets never deallocated you can use it even after the autorelease pool would have deallocated it.

This just covers your wrong memory management. And you should definitely not rely on this behaviour.


Edit. there is not much more to say. The NSString that you've created with stringWithString:literal will simply point to the location of literal in memory.

A little example:

NSString *string = @"Foo";
NSLog(@"%@ - %p", string, string);
NSString *string2 = string;
NSLog(@"%@ - %p", string2, string2);
NSString *string3 = [string copy];
NSLog(@"%@ - %p", string3, string3);
NSString *string4 = [string retain];
NSLog(@"%@ - %p", string4, string4);
NSString *string5 = [NSString stringWithString:string];
NSLog(@"%@ - %p", string5, string5);
NSString *string6 = [[NSString alloc] initWithString:string];
NSLog(@"%@ - %p", string6, string6);

you will see they all point to the same address.

2011-02-22 13:24:41.202 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.204 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.206 xxx[40783:207] Foo - 0x74120
2011-02-22 13:24:41.207 xxx[40783:207] Foo - 0x74120

And all of them will never get deallocated. So you could access string5 from some other method in your code and it would still point to the address 295740, and the NSString "Foo" would still be there.

But a NSString object that does not point to a string literal would be deallocated at this time, and you would get a bad access exception.

You are violating the memory management rules but you will never notice it if you only use string literals. Until the behaviour of the compiler changes.

So do it right, learn proper memory management and don't rely on internals. Retain all your autoreleased objects if you need them later. Even if they point to string literals

1 Comment

post slightly edited. I had already done what Daniel has responded with and yes figured out it works. Could you be more elaborate as to why stringWithFormat needs a retain and stringWithString works without any such fuss?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.