iPhone app crash when converting formatted NSString to UTF8 char *
I want to convert a NSString into a const char * in order to access a sqlite DB.
This works:
NSString *queryStatementNS = @"select title fro开发者_开发技巧m article limit 10";
const char *queryStatement = [queryStatementNS UTF8String];
This causes a crash in the simulator (without any stacktrace):
NSString *queryStatementNS = [NSString stringWithFormat:@"select title from article limit %d", 10];
const char *queryStatement = [queryStatementNS UTF8String];
Can anybody tell me, what the stringWithFormat method changes in the String to make the conversion to UTF8 (or to ASCII using cStringUsingEncoding:NSASCIIStringEncoding) crash? The same crash happens also when passing no arg at all to the stringWithFormat. Could it be related to memory management somehow?
From the documentation:
The returned C string is automatically freed just as a returned object would be released; you should copy the C string if it needs to store it outside of the autorelease context in which the C string is created.
Your problem is that queryStatement is being freed when queryStatementNS gets deallocated, and as queryStatementNS is autoreleased you don't know exactly when this is going to occur. You can either retain queryStatementNS by calling
[queryStatementNS retain]
at some point in that function (remember to release it when you want to relinquish ownership), you can explicitly create a non-autoreleased string to deal with yourself by saying
NSString* query = [[NSString alloc] initWithFormat:@"a string! %d", 10, nil]
(as an aside, note the nil - if you don't have it there xcode will give you a missing sentinel warning)
or you can copy the output of [queryStatementNS UTF8String] to your const char* queryStatement as you would in plain C, with strcopy or whatever.
The reason the first example you give continues to work is that you're setting a pointer to a string literal, @"select title from article limit 10". The objective c compiler ensures that there's only ever one instance of this string in memory, no matter how many times you reference it in your code. Thus, it doesn't obey the standard memory management conventions of objective c and your pointer remains valid outside of the autoreleased context.
精彩评论