将格式化的NSString转换为UTF8 char *时,iPhone应用程序崩溃

时间:2010-10-15 18:14:35

标签: iphone objective-c xcode

我想将NSString转换为const char *以访问sqlite DB。

这有效:

NSString *queryStatementNS = @"select title from article limit 10";
const char *queryStatement = [queryStatementNS UTF8String];

这会导致模拟器崩溃(没有任何堆栈跟踪):

NSString *queryStatementNS = [NSString stringWithFormat:@"select title from article limit %d", 10];
const char *queryStatement = [queryStatementNS UTF8String];

有人能告诉我,stringWithFormat方法在String中的变化是什么,以便转换为UTF8(或使用cStringUsingEncoding:NSASCIIStringEncoding)转换为ASCII?当没有将arg传递给stringWithFormat时也会发生同样的崩溃。它能以某种方式与内存管理有关吗?

1 个答案:

答案 0 :(得分:0)

来自文档:

  

返回的C字符串是自动的   释放就像返回的对象一样   被发布;你应该复制C   字符串,如果它需要存储在外面   自动释放上下文中的   创建了C字符串。

你的问题是当queryStatementNS被解除分配时正在释放queryStatement,并且当queryStatementNS被自动释放时你不确切知道何时会发生这种情况。您可以通过调用

来保留queryStatementNS
[queryStatementNS retain]

在该函数的某个时刻(记得在你想放弃所有权时释放它),你可以通过说明

明确地创建一个非自动释放的字符串来处理你自己。
NSString* query = [[NSString alloc] initWithFormat:@"a string! %d", 10, nil]

(顺便说一下,注意零 - 如果你没有,那么xcode会给你一个丢失的哨兵警告)

或者你可以将[queryStatementNS UTF8String]的输出复制到const char * queryStatement,就像在普通的C中一样,使用strcopy或其他任何东西。

您给出的第一个示例继续工作的原因是您正在设置指向字符串文字的指针,@“从文章限制10中选择标题”。目标c编译器确保在内存中只有一个这个字符串的实例,无论你在代码中引用它多少次。因此,它不遵守目标c的标准内存管理约定,并且您的指针在自动释放的上下文之外仍然有效。