当类包含数组时,Swift 3枚举泄漏内存

我在Swift中发现了内存泄漏。 它给了我恶梦,因为我的代码到处都是小漏洞,然后我设法减less到这个小例子,

import UIKit enum LeakingEnum { case LeakCase, AnotherLeakCase } class Primitive { var lightingType: LeakingEnum = .LeakCase var mysub : [Int] = [] init() { mysub.append(80) } } class ViewController: UIViewController { var prim: Primitive? override func viewDidLoad() { super.viewDidLoad() prim = Primitive() } } 

如果你在iPhone上运行这个程序和configuration文件,你会发现在Array._copyToNewBuffer这个泄漏,

仪器检测到内存泄漏

如果我删除对mysub.append的调用,它将停止泄漏。 如果我从Primitive删除枚举,它也会停止泄漏。 所有我有一个枚举泄漏这样的类。 什么发生在Swift枚举?

Swift 3,Xcode 8.2.1和iOS 10.2在iPhone6和iPad Pro上转载。 无法在模拟器或iOS 9.3.2的设备中重现。 你可以在这里下载一个最小的示例应用程序: https : //github.com/endavid/SwiftLeaks

这是一个已知的错误? 有什么解决办法吗?

编辑:

因为这让我想起了另一个枚举错误, Accessor仅在Swift 1.2 / 2.0 Release版本中给出了错误的值 ,我试图使枚举@objc Int枚举,但它仍然泄漏。 然而,使lightingType直接一个Int确定泄漏…

编辑2:更新我的iPhone到10.3和Xcode到8.3后,泄漏消失了。 这似乎是一个iOS 10.2的问题…

嘿@endavid设法一贯地复制这个问题。 我们花了很长的时间试图弄清楚发生了什么,你的post帮了大忙!

这里是示例回购: https : //github.com/Giphy/ios-memory-leak-sample

雷达: https : //openradar.appspot.com/radar? id = 4992108083544064

我们正在开发软件开发工具包,同样的问题浮出水面,有一点点不同。 因为我们想要互操作的东西,所以我们在枚举定义中添加了@objc ,并且事情开始按照您描述的方式泄漏,因为您的类有两个属性,一个枚举和一个可变数组。

一致地转载泄漏:

 // Without @objc this enum won't leak // however when this enum is included in a class // which contains an array, it will leak @objc enum leakingObjCMarkedEnum: Int { // Just some random cases. case apple, orange } // Wrapper class which contains an enum and Array // The class needs to contain the the Array in order for // the Enum to leak. class WrapperClass { // Optional enums marked with @objc will leak. var leakyOptionalEnum: leakingObjCMarkedEnum? // Include an array to trigger this behaviour. // Empty arrays won't cause the leak, so lets add an arbitrary Int var myArray: [Int] = [80] } class ViewController: UIViewController { // Hang on to a reference to our Wrapper Class instance. var wc: WrapperClass? override func viewDidLoad() { super.viewDidLoad() // Allocate an instance of our class // and things will start leaking at this point. wc = WrapperClass() } } 

解决方法:

如果我们将可选的枚举类属性转换为非可选,则泄漏将消失。

 // Let's convert the optional property to a non-optional var leakyOptionalEnum: leakingObjCMarkedEnum = .orange 

编辑:

这是由家伙@苹果修复: https : //bugs.swift.org/browse/SR-5625 PR: https : //github.com/apple/swift/pull/11341