0

我正在尝试构建一个用于处理所有 sqlite3 工作的类,但我遇到了一个我无法解释的 EXC_BAD_ACCESS。一般来说,我是 Objective-C 开发和内存管理的新手,所以如果这是一个愚蠢的问题,我深表歉意。

初始化类时,我获取数据库文件的路径并保留它:

NSArray * documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
databasePath = [[[documentPaths objectAtIndex:0] stringByAppendingPathComponent:@"Database.sql"] retain];

然后我尝试使用它,它在我身上崩溃了:

if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { // crashes

奇怪的是,不同函数中完全相同的行可以完美运行。我尝试将变量初始化添加到该行的上方,但无济于事:

NSArray * documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
databasePath = [[[documentPaths objectAtIndex:0] stringByAppendingPathComponent:@"Database.sql"] retain];

if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { // crashes

在这两种情况下,保留计数都是 2。

但是,在其中放置任何形式的静态文本都可以正常工作:

databasePath = @"I have a balloon";
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { // fine
// or
if (sqlite3_open([@"APPLES!" UTF8String], &database) == SQLITE_OK) { // fine

更多的实验表明是UTF8String函数崩溃了,但我不明白为什么。

编辑:更多的实验使我能够调用UTF8String函数,但甚至不能使用结果:

const char * test = [databasePath UTF8String];
NSLog(@"%@", [NSString stringWithUTF8String:test]); // fine
if (sqlite3_open(test, &database) == SQLITE_OK) { // fails

编辑:搞砸了,发现问题出在我传递给函数的参数中。我到处都有断点,所以我 100% 确定它失败的点位于我指定的行,该行不使用传递的变量,但不知何故它导致一切都失败了。有时。我不知道它是怎么出错的,但我重写了整个东西,改变了我的函数调用,现在它可以工作了。

感谢所有回答的人。

4

5 回答 5

1

databasePath在进行 open 调用之前,您是否检查过变量的内容?添加一条NSLog语句,或者使用调试器来查找它的值——它可能是NULL,它可能无法由sqlite3_open函数处理,或者甚至可能是由于路径有效而导致崩溃,并且它指向的数据库是腐败。

于 2009-12-30T14:33:22.720 回答
1

我的猜测是数据库变量没有正确声明。它似乎与数据库的路径没有任何关系。

你是这样声明数据库的吗?:

sqlite3 *database;
于 2009-12-30T15:26:34.567 回答
1

我怀疑你在追求错误的问题。您没有显示崩溃转储,但声称打开“APPLES!” '很好' 这听起来很奇怪 - 你肯定没有那个名字的数据库吗?

你确定你没有一个坏的数据库文件 - 即你试图打开的数据库文件以某种方式损坏了吗?

于 2009-12-30T21:45:15.897 回答
1

我认为您必须发布崩溃日志,您的崩溃毫无意义。您发布的代码应该可以工作。

于 2009-12-30T23:40:28.900 回答
0

尝试在变量上使用副本而不是保留 - 它会生成字符串的不可变副本,因此它不应该改变或消失。

编辑::

当您简单地键入时会发生什么

if (sqlite3_open[@"myDatabase.sqlite" UTF8String], &database) == SQLITE_OK) {

你也确定

NSArray * documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
databasePath = [[[documentPaths objectAtIndex:0]
stringByAppendingPathComponent:@"Database.sql"] retain];

实际上是返回数据库在哪里?

我用来从 kFilename 是数据库文件的 app 目录中获取数据库的代码是:

- (NSString *)dataFilePath{

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    return [documentsDirectory stringByAppendingPathComponent:kFilename];
}

然后使用它我做:

if(sqlite3_open([[self dataFilePath] UTF8String], &database) != SQLITE_OK){

这适用于我的 iPod touch 和 iPhone 模拟器。

编辑2::

我刚刚使用了您的上述方法,它似乎在这里工作 - 我知道这听起来很愚蠢,但您是否尝试过重新启动?模拟器可能发生了一些奇怪的事情

于 2009-12-30T14:30:50.733 回答