【问题标题】:Objective-C strange EXC_BAD_ACCESSObjective-C 奇怪的 EXC_BAD_ACCESS
【发布时间】:2013-10-23 23:40:38
【问题描述】:

我的代码因 EXC_BAD_ACCESS 错误而崩溃,我不知道如何调试。

这是代码:

NSUInteger lineCount = self.lineBeginnings.count;
NSUInteger lineBeginnings[lineCount];
[self.lineBeginnings getIndexes:lineBeginnings maxCount:lineCount inIndexRange:nil];

它在最后一行崩溃,EXC_BAD_ACCESS (code=2, address=0x...)

注意上面的两行,它能够完美地读取 self.lineBeginnings,但是在调试器中我得到:

(lldb) p [self lineBeginnings]
error: Trying to put the stack in unreadable memory at: 0x7fff5d15e310.
(lldb) p _lineBeginnings
(NSMutableIndexSet *) $1 = 0x0000610000059b90
(lldb) po _lineBeginnings
[no Objective-C description available]

lineBeginnings 也不能在 GUI 范围浏览器中正确显示(所有其他变量都会显示),并且尝试“查看 lineBeginnings 的内存”会给出完全空的内存视图。

lineBeginnings 变量存储为强 @property,它是在应用程序委托的 init 方法中创建的可变索引集,并且在应用程序运行时从不删除。有一个后台操作队列写入它,但它使用dispatch_sync(dispatch_get_main_queue()) 切换到主线程进行所有修改。

我不确定如何进一步调试?很难重现,我必须调整窗口的大小长达一分钟(这会导致在后台队列中重新创建 lineBeginnings 变量,当给定 180MB 数据时,这个过程需要大约 5 分钟),以便发生这种崩溃。

对我来说,这看起来像是缓冲区溢出还是什么?如何追踪它?

该文件的源代码在这里:https://gist.github.com/abhibeckert/7128740(崩溃在第 254 行)。

【问题讨论】:

    标签: objective-c cocoa crash


    【解决方案1】:

    在 180 MB 中可能有数百万行开头?因此,您在堆栈上分配数百万个八字节字的数组。线程的堆栈通常不会那么大。

    你应该在堆上分配数组,使用malloc

    您的问题称为堆栈溢出。听起来很熟悉?

    【讨论】:

    • 谢谢,我是一位经验丰富的 Obj-C 程序员(从 OS X 10.0 开始!),从未正确学习过 C,所以当我需要学习低级的东西时我会很挣扎。所以基本上你是说lineCount 的大小有一个相当小的限制?我的代码正在执行软包装文本,lineBeginnings 是数据中的字节偏移量,核心文本表示该行应该被包装。这是一个重写 NSTextView 以解决我遇到的一些瓶颈的实验。
    • lineCount 崩溃时约为 570 万。谢谢,我会考虑使用 malloc。无论如何,NSIndexSet 也是错误的数据集,因为它在内部使用 NSRange 并且我的索引从不连续,但它没有引起任何性能问题,所以我把它留在那里。
    • 没错。本地(自动)变量lineBeginnings 在堆栈上分配。在这种情况下(作为 VLA),当数组的大小已知时,堆栈将调整为正确的大小。我不确定线程​​堆栈的特定大小,但一旦元素数量超过几千,您应该切换到堆分配内存。
    • 当您不知道它需要多大时,使用 malloc() 的最佳技术是什么?通常它只有几百字节,但偶尔(如果用户打开一个异常大的文件)它会是数百兆字节甚至可能是千兆字节。我应该只 malloc 1MB 左右,如果它用完 malloc 一些 10 倍大的新内存并复制数据,还是什么?在大型文本文件(mysql 数据库转储或其他)上执行换行需要核心文本分钟,这就是我离开 NSTextView 的原因
    • 你可以像以前一样做:只分配需要的缓冲区。 64 位进程中的分配实际上不会失败。并且只要不被触动,页面就不会被映射,也不会使用物理内存。
    【解决方案2】:

    我遇到了同样的问题,花了 2 天后,我发现我的 getter 调用了几次,因为我在 getter 中使用了 self。

     if(! _openSectionIndexes) _openSectionIndexes = [NSMutableArray new];
    
    if( _openSectionIndexes.count != _requests.count)
    {
        for (int i =0; i < _requests.count; i++)
        {
            [self.openSectionIndexes addObject: @(NO)];// here was the problem, replaced it with _openSectionIndexes
        }
    }
    
    return _openSectionIndexes;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多