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 v开发者_高级运维alue persisted. Hence the question.
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.
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
精彩评论