Swift 1.2中的神秘崩溃 - 仅在版本中构建

mat*_*att 10 debugging xcode swift

更新到Xcode 6.3(beta 1)和Swift 1.2之后,我的所有应用程序都只在Release版本中神秘崩溃.在Debug版本中更新我的Swift 1.2代码后,它们工作正常.调试器没有给出的意义,其中的崩溃正在发生,而且目前尚不清楚为什么.一些崩溃是

malloc:***对象0x7ff0c3824800的错误:没有分配被释放的指针***在malloc_error_break中设置一个断点来调试

其他人是"无法识别的选择者",但他们毫无意义; 选择器被发送到的对象甚至不是我知道使用的对象.内存管理似乎出了问题,因此一个对象正在替换另一个对象.

究竟是什么导致了这个?在调用堆栈中没有任何用处(因此我甚至不知道我的代码中发生崩溃的位置)并且当我单步执行代码时,调试器的变量窗格中没有变量显示(因此我甚至无法使用看看事物的价值观,我怎么能开始追踪呢?

mat*_*att 12

令人惊讶的是,我确实跟踪了这一点,主要是通过删除大型样本中的代码,直到我只是这个(它是一个视图控制器):

class LessonListController: UIViewController {
    var terms : [Term]
    // var terms : NSArray
    init(terms data:NSArray) {
        let arr = data.sortedArrayUsingDescriptors([NSSortDescriptor(key: "lessonSection", ascending: true)])
        self.terms = arr as! [Term]
        // self.terms = arr
        super.init(nibName:"LessonList", bundle:nil)
    }
    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    @IBAction func doDismiss(sender: AnyObject) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果(在发布版本中)我们提供了这个视图控制器然后解除它,我们就会崩溃 - 在dealloc中,这证明了我的理论认为它是内存管理的一个问题.

隔离了代码后,我能够尝试各种替代方案.很明显,问题是属性var terms : [Term](因为Swift在引擎盖下做的唯一事情dealloc是释放这个数组).正如你在我看到的那样,这个属性的值init是一个来自Cocoa(thru sortedArrayUsingDescriptors)的NSArray,并且已被强制转换为Swift数组.通过反复试验,我发现:

  • 如果我们更改实现以使属性为NSArray(请参阅注释掉的替代行),我们不会崩溃.

  • 或者,如果我们不排序(因此这个NSArray不是来自Cocoa),我们不会崩溃.

  • 或(等待它),如果我们更换self.terms = arr as! [Term]self.terms = arr as NSArray as! [Term],我们不死机!

但第三种选择是解决方法.我在我的所有应用程序中查看了我的所有代码,寻找as! [SomeType]演员阵容并将其全部替换掉as NSArray as [SomeType],我的所有崩溃都消失了!

我的理论是,在优化的Release版本中,Swift的内存管理出现了问题,只是在非常具体的情况下,NSArray从Cocoa到达并且[AnyObject]在我们的代码可以掌握它之前为我们桥接.这样的NSArray没有正确地过桥.但是通过转换为NSArray然后返回到特定的[SomeType]Swift数组,问题就解决了.

当然,我认为当苹果公司解决这个问题时,他们会修复它,然后我们可以停止使用这种解决方法.但在此之前,我的应用程序再次在Release版本中运行.