4

私はしばらくの間エンタープライズiPadアプリを開発してきました。アプリの開発はほぼ2年前に開始されたため、デフォルトのSQLiteライブラリ(sqlite3.dylib)ではデフォルトでFTSが有効になっていないため、ソースから独自のバージョンのSQLiteをコンパイルする必要がありました。

それ以来、すべてが正常に機能していました。私は常にGCCをプロジェクトコンパイラとして使用してきました。

問題は、プロジェクト全体をARCを使用するように変換しようとしているということです。そのためには、AppleのLLVMコンパイラを使用する必要があります。

それでおしまい。コンパイラを変更すると(GCC4.2からLLVM3.1または4.0に、ARCに変換せずに、他に何も変更せずに)、アプリは正常にビルドされ、FTSクエリを除いて、すべてが正常に実行されます。最も単純なもの。それらは実行され、常に結果なしで返されます(ただし、SQLITE_OKコードを使用します)。

私はここで立ち往生しています。私はすでにWWDC'12でAppleのエンジニアと話をしましたが、解決策が見つかりませんでした。

アプリはGCCで正常に動作しているため、不正な形式のクエリなどである可能性は低いと保証します。また、ターミナルバージョンのSQLiteで(またはBaseなどの他のアプリを使用して)クエリを実行することもできます

古いバージョンのSQLiteも使用していましたが、最新バージョン(3.7.13)に更新しました。すべてが同じままです。また、Macに付属のsqliteがFTS(!!!)をサポートし、自分のバージョンを削除してAppleのバージョンを使用できるようになったことに気づきました(いつからかはわかりません)。問題は、私はまったく同じ振る舞いをしているということです。

解決策を探していましたが、見つかりませんでした。armv6とコンパイラの最適化(-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");
}
4

1 に答える 1

3

結局のところ、私はバグを見つけました。それは私のコードにありました。要約すると、私が見つけたもの:私がそのようなものを持っている場合(私はそれが奇妙/間違っていることを知っています):

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

このコードがgccでコンパイルされている場合、ログに記録される値は1になり、llvmでコンパイルされている場合は0になります。

理由はわかりませんが、それは別の質問です:)

于 2012-06-28T18:04:29.997 に答える