我一直在開發企業iPad應用程序一段時間。自從2年前開始應用程序開發以來,我需要從源代碼編譯自己的SQLite版本,因爲默認的SQLite庫(sqlite3.dylib)沒有默認啓用FTS。當使用iOS上的LLVM編譯時,Sqlite FTS不起作用
好吧,一切工作都很好。我一直在使用GCC作爲項目編譯器。
事情是,現在我試圖將我的整個項目轉換爲使用ARC。爲此,我需要使用Apple的LLVM編譯器。
就是這樣。當我更改編譯器(從GCC 4.2到LLVM 3.1或4.0,而不轉換爲ARC,並且沒有更改其他任何東西)時,我的應用程序生成良好,除了通過我的FTS查詢,一切都運行正常最簡單的。他們運行並返回總是沒有結果(儘管SQLITE_OK代碼)。
我被困在這裏。我已經在WWDC'12與蘋果工程師交談過,但我們找不到任何解決方案。
我保證它不太可能是一個格式錯誤的查詢或類似的東西,因爲該應用程序與GCC工作正常。另外,我能夠在終端版本的SQLite上運行查詢(或使用其他應用程序,如Base)
我也在使用舊版本的SQLite,但我已更新到最新版本日期(3.7.13)。一切都保持不變。我也注意到,現在(我不知道從什麼時候開始)Mac上的sqlite支持FTS(!!!),我可以刪除自己的版本並使用Apple的版本。事情是,我有完全相同的行爲。
我一直在尋找解決方案,但找不到一個。我發現了一些與armv6和編譯器優化相關的bug(可以使用-mno-thumb標誌修復),但這不是我的情況。我還注意到,當我使用Clang分析自定義的sqlite文件時,它指出了許多「潛在的錯誤」。
我有這個非懷疑的觀點,我(仍)不相信它是LLVM或SQLite的錯誤。在處理錯誤之前,我更願意檢查所有可能的東西。也許我忘了配置一些東西,或者需要向編譯器添加一些我沒有做的標誌。
我很感激任何幫助。同樣,該錯誤僅發生在使用LLVM編譯的項目上(即使使用默認的sqlite)。如果我在終端版本的sqlite3上運行相同的查詢,一切都很順利。
更新:
此代碼有效。它使用fts創建一個新的數據庫,一個新的虛擬表格,插入一些項目然後執行選擇。稍後我會嘗試更復雜的查詢,但現在看來,我的應用程序的問題可能和預期的一樣,是我的代碼中的一個錯誤。
NSArray *dirPaths = dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
sqlite3 *database;
// Build the path to the database file
NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"test.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
NSError *error = nil;
[filemgr removeItemAtPath:databasePath error:&error];
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt = "CREATE VIRTUAL TABLE IF NOT EXISTS pages USING fts3(title, body);";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Failed to create table");
} else {
sql_stmt = "INSERT INTO pages(docid, title, body) VALUES(53, 'Home Page', 'SQLite is a software...');";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Failed to insert");
}
sql_stmt = "INSERT INTO pages(title, body) VALUES('Download', 'All SQLite source code...');";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(@"Failed to insert");
}
}
sqlite3_stmt *statement;
const char *query_stmt = "select * from pages where body match 'soft*';";
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(@"%@ - %@", [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)],
[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]);
} else {
NSLog(@"no results");
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
} else {
NSLog(@"Failed to open/create database");
}
你試過把sqlite3的單獨的靜態庫和編譯這個庫LLVM-GCC,而不是鐺?那它有用嗎? –
是的,我有。有趣的是,如果我這樣做,同樣的問題發生。如果我做的是相反的(用Clang編譯我的靜態SQLite庫,然後使用GCC編譯我的整個項目),它可以工作。我不知道這背後的邏輯在哪裏。 –
也許這是由clang編譯器(但gcc編譯器生成的代碼不觸發內存損壞)觸發的其餘代碼中的一些內存損壞。 –