簡體   English   中英

iOS應用程序中的SQLite C函數導致EXC_BAD_ACCESS

[英]SQLite C function in iOS application results in EXC_BAD_ACCESS

在一個iOS應用程序中,我試圖從具有100萬行的表中的SQLite字段中刪除變音符號。

編輯 我引用原始答案已經由其作者更新 ,以反映下面接受的答案。 對於任何嘗試做同樣事情的人來說,這都是最好的答案。

我從Rob的較早回答中有了一個很好的開端。 出於這個問題的目的,我試圖使用INSERT INTO ... SELECT ... FROM ...語句將表復制到另一個表。 直到我引入一個從字段中去除重音符號和其他變音符號的C函數,此方法才能正常工作:

INSERT INTO DestinationTable (MasterField, SubField, IndexID) SELECT unaccented(MasterField), SubField, IndexID FROM SourceTable

引入unaccented unaccented()函數后,我經常得到一個EXC_BAD_ACCESS,我將在下面指定。 但令人着迷的是,SQLite操作有時會成功完成所有100萬行 當我將負載擴展到500萬行復制時,應用程序將始終崩潰。

TL; DR

這是我的源代碼,在第一個函數的底部注釋了EXC_BAD_ACCESS的要點:

#import <sqlite3.h>

sqlite3 *db;

void unaccented(sqlite3_context *context, int argc, sqlite3_value **argv)
{
    if (argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_TEXT) {
        sqlite3_result_null(context);
        return;
    }

    @autoreleasepool {
        NSMutableString *string = [NSMutableString stringWithUTF8String:(const char *)sqlite3_value_text(argv[0])];
        CFStringTransform((__bridge CFMutableStringRef)string, NULL, kCFStringTransformStripCombiningMarks, NO);

        char *buf = sqlite3_malloc(sizeof(char) * [string length] + 1);
        strcpy(buf, [string UTF8String]);

        sqlite3_result_text(context, buf, -1, sqlite3_free);
    } // This is where I usually get "EXC_BAD_ACCESS (code=1, address=...)"
}

@implementation MyClass

- (void)myMethod
{
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachesDir = [documentPaths objectAtIndex:0];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;

    NSDirectoryEnumerator *directoryEnumerator = [fileManager enumeratorAtPath:[[NSBundle mainBundle] resourcePath]];

    NSString *fileName;
    while (fileName = [directoryEnumerator nextObject])
    {
        if ([fileName hasSuffix:@".sqlite"])
        {
            if (![fileManager fileExistsAtPath: [cachesDir stringByAppendingPathComponent:fileName]] == YES)
            {
                if (![fileManager copyItemAtPath:[[NSBundle mainBundle] pathForResource:fileName ofType:@""] toPath:[cachesDir stringByAppendingPathComponent:fileName] error:&error])
                {
                    NSLog(@"Error description - %@ \n", [error localizedDescription]);
                    NSLog(@"Error reason - %@", [error localizedFailureReason]);
                }
                else
                {
                    NSLog(@"HAI %@", fileName);

                    [self openDB:[cachesDir stringByAppendingPathComponent:fileName]];

                    NSString *sqlCommand = @"INSERT INTO DestinationTable (MasterField, SubField, IndexID) SELECT unaccented(MasterField), SubField, IndexID FROM SourceTable";

                    char *sqlError;
                    if (sqlite3_exec(db, [sqlCommand UTF8String], NULL, NULL, &sqlError) != SQLITE_OK)
                    {
                        NSLog(@"sqlite3_exec INSERT NOT SQLITE_OK with error: %d: %s", sqlite3_errcode(db), sqlite3_errmsg(db));
                    }

                    [self closeDB];

                    NSLog(@"KTHXBYE %@", fileName);
                }
            }
        }
    }
}

- (void) openDB: (NSString *)filePath
{
    if (sqlite3_open([filePath UTF8String], &db) != SQLITE_OK)
    {
        sqlite3_close(db);
    }
    else
    {
        [self createUnaccentedFunction];
    }
}

- (void) closeDB
{
    sqlite3_close(db);
}

- (void)createUnaccentedFunction
{
    if (sqlite3_create_function_v2(db, "unaccented", 1, SQLITE_ANY, NULL, &unaccented, NULL, NULL, NULL) != SQLITE_OK)
    {
        NSLog(@"%s: sqlite3_create_function_v2 error: %s", __FUNCTION__, sqlite3_errmsg(db));
    }
}

關於我在做什么錯的任何發現嗎?

可能是這樣的:

char *buf = sqlite3_malloc(sizeof(char) * [string length] + 1);
strcpy(buf, [string UTF8String]);

您分配的是Unicode字符length ,而不是UTF-8字節。

然后, strcpy可能會嘗試寫入無效的內存。

我建議您使用以下方法讓SQLite復制字符串:

sqlite3_result_text(context, [string UTF8String], -1, SQLITE_TRANSIENT);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM