2010-10-15 68 views
0

我想將NSString轉換爲const char *以便訪問sqlite數據庫。當將格式化的NSString轉換爲UTF8時,iPhone應用程序崩潰char *

這工作:

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方法的變化使轉換爲UTF8(或使用cStringUsingEncoding:NSASCIIStringEncoding到ASCII)崩潰?在沒有將任何參數傳遞給stringWithFormat時也會發生同樣的崩潰。莫名其妙地與內存管理有關嗎?

+1

stringWithFormat是否調用與UTF8String方法不同的地方或方法?如果是這樣,第二個例子中的autorelease對象queryStatementNS可能已經發布。第一個例子使用一個常量,它不是一個autorelease對象。 – hotpaw2 2010-10-15 18:25:24

+0

這一切都在一個地方,就像在這個例子中一樣。但是,我添加了[queryStatementNS retain];在這些線之間,現在它工作。 – Sven 2010-10-16 08:17:10

回答

0

從文檔:

返回的C字符串自動是 剛剛釋放作爲返回的對象將 被釋放;如果需要將C 字符串存儲在創建C字符串的自動釋放上下文的 之外,則應複製C 字符串。

你的問題是,當queryStatementNS被取消分配時,queryStatement被釋放,而當queryStatementNS被autoreleased時,你不知道到底什麼時候會發生。你可以通過調用

[queryStatementNS retain] 

在該功能的某一點或者保留queryStatementNS(記得要釋放它,當你想放棄所有權),你可以明確地說

創建非自動釋放字符串處理自己
NSString* query = [[NSString alloc] initWithFormat:@"a string! %d", 10, nil] 

(順便說一句,請注意零 - 如果你沒有它存在的Xcode會給你一個缺少定點警告)

,或者你可以在[queryStatementNS UTF8字符串]將輸出複製到你的爲const char * queryStatement就像你在普通的C中一樣,strcopy或其他。

您給出的第一個示例繼續工作的原因是,您要設置一個指向字符串文字的指針,@「從文章限制10中選擇標題」。目標c編譯器確保在內存中只有一個此字符串實例,無論您在代碼中引用了多少次。因此,它不遵守目標c的標準內存管理約定,並且指針在自動發佈的上下文之外保持有效。

+0

謝謝你的回答,明天我會試着採用我的代碼。當你來自Java時,整個內存分配和釋放都會讓你感到困惑(我最近一次在12年前寫過C代碼......)。如果我在.h文件中聲明NSString並在其上聲明@parameter(nonatomic,retain),它是否也解決了我的問題?我認爲我必須手動發佈queryStatementNS *,因爲我在本地方法中定義了它,並且對此處的autorelease概念一無所知。我真的需要閱讀更多關於這個alloc/retain/release的東西。謝謝! – Sven 2010-10-15 22:08:13

+0

是的,將NSString保留爲實例變量可以解決您的問題。一定要在dealloc方法中釋放它! – johnw188 2010-10-17 10:04:06