【问题标题】:Inexplicable EXC_BAD_ACCESS in the iPhone simulatoriPhone模拟器中莫名其妙的EXC_BAD_ACCESS
【发布时间】:2009-12-30 14:12:28
【问题描述】:

我正在尝试构建一个类来处理所有 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% 确定它失败的点位于我指定的行,该行不使用传递的变量,但不知何故它导致一切都失败了。有时。我不知道它是怎么出错的,但我重写了整个东西,改变了我的函数调用,现在它可以工作了。

感谢所有回答的人。

【问题讨论】:

  • 我不确定这是否是问题所在,但如果 documentPaths 为 nil,则您调用 sqlite3_open 时第一个参数为空。

标签: iphone objective-c sqlite memory-management exc-bad-access


【解决方案1】:

在进行公开调用之前,您是否检查过databasePath 变量的内容?添加一个NSLog 语句,或者使用调试器来查找它的值——它可能是NULL,它可能无法由sqlite3_open 函数处理,或者甚至可能是因为路径是有效,并且它指向的数据库已损坏。

【讨论】:

  • 内容丰富。我测试了 UTF8String 函数并从中得到了结果,但是一旦我尝试将任何内容传递给 sqlite3 函数,它就会崩溃。
  • 内容是什么……?如果将其作为常量字符串传递,它仍然会崩溃吗?
【解决方案2】:

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

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

sqlite3 *database;

【讨论】:

  • 是的,就在崩溃线的正上方。我没有想到要添加它,因为我推断字符串是问题所在。
【解决方案3】:

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

您确定没有损坏的数据库文件 - 即您尝试打开的数据库文件已损坏?

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      编辑::

      当你简单地输入时会发生什么

      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 模拟器。

      EDIT2::

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

      【讨论】:

      • 没有任何区别。复制查找目录时生成的字符串没有帮助,在我使用它之前复制字符串也没有帮助。
      猜你喜欢
      • 1970-01-01
      • 2019-03-12
      • 2012-05-19
      • 1970-01-01
      • 2012-03-12
      • 2019-02-04
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多