2012-06-18 30 views
4

我一直在開發企業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"); 
} 
+0

你試過把sqlite3的單獨的靜態庫和編譯這個庫LLVM-GCC,而不是鐺?那它有用嗎? –

+0

是的,我有。有趣的是,如果我這樣做,同樣的問題發生。如果我做的是相反的(用Clang編譯我的靜態SQLite庫,然後使用GCC編譯我的整個項目),它可以工作。我不知道這背後的邏輯在哪裏。 –

+0

也許這是由clang編譯器(但gcc編譯器生成的代碼不觸發內存損壞)觸發的其餘代碼中的一些內存損壞。 –

回答

3

畢竟,我發現了這個錯誤。這是在我的代碼。總之,這是我已經找到了: 如果我有類似的東西(我知道它的怪異/錯):

int a = 0; 
a = a++; 
NSLog(@"%d", a); 

記錄的值爲1,如果這個代碼是用gcc和0,如果編譯用llvm編譯。

我不知道爲什麼,但這是另一個問題:)

+1

這看起來像是對舊編譯器的錯誤修復。如果你有一個= ++ a,它會按預期工作。 – nobre

相關問題