当类包含数组时,Swift 3枚举泄漏内存 [英] Swift 3 enums leak memory when the class contains an array
问题描述
import UIKit
/ pre>
枚举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和配置文件上运行此程序,您将在
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
这是一个已知的错误吗?有没有工作?
编辑:
因为这提醒我另一个枚举错误,访问者在Swift 1.2 / 2.0版本版本中给出错误的值,我尝试使枚举为code> @objc Int 枚举,但它仍然泄漏。但是,直接将
lightingType
直接Int
可以修复泄漏...
编辑2:
将iPhone更新为10.3,将Xcode更新为8.3后,泄漏就消失了。这似乎是iOS 10.2的一个问题...解决方案嘿@endavid设法一致地复制这个问题。我们花了很长时间来弄清楚发生了什么,你的帖子帮助了很多!
这是示例repo: https://github.com/Giphy/ios-memory-leak-sample
雷达: https://openradar.appspot.com/radar?id = 4992108083544064
我们开发的SDK和相同的确切问题浮出水面,差别很小。因为我们想要交互的东西,我们在枚举定义中添加了
@objc
,事情开始泄漏,正如你所描述的那样,你的类有两个属性,一个枚举和一个可变数组
一致地转载泄漏:
//没有@objc这个枚举不会泄漏
//但是当这个枚举包含在一个包含数组的类
//中时,它会泄漏
@objc enum leakingObjCMarkedEnum:Int {
//只是一些随机的情况。
case apple,orange
}
//包含枚举和数组的包装类
//该类需要包含该数组,以便
//枚举泄漏。
class WrapperClass {
//用@objc标记的可选枚举将泄漏。
var leakyOptionalEnum:leakingObjCMarkedEnum?
//包含数组来触发此行为。
//空数组不会导致泄漏,所以可以添加任意的Int
var myArray:[Int] = [80]
}
class ViewController :UIViewController {
//挂起对我们的Wrapper类实例的引用。
var wc:WrapperClass?
覆盖func viewDidLoad(){
super.viewDidLoad()
//分配我们的类
//的一个实例,事情会开始泄漏在此刻。
wc = WrapperClass()
}
}
:
如果我们将可选的枚举类属性转换为非可选项,则泄漏将消失。
//我们将可选属性转换为非可选的
var leakyOptionalEnum:leakingObjCMarkedEnum = .orange
编辑:
这是由@ @ Apple修复的:
https://bugs.swift.org/browse/SR-5625
PR: https://github.com/apple/swift/pull/11341I found a memory leak in Swift. It gave me nightmares because my code was full of small leaks everywhere, and then I managed to reduce it to this small example,
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() } }
If you run this program on an iPhone and Profile with Instruments, you'll find this leak in
Array._copyToNewBuffer
,If I remove the call to
mysub.append
, it stops leaking. If I remove the enum fromPrimitive
, it stops leaking as well. All the classes where I have an enum leak like this. What's going on with Swift enums?Reproduced in Swift 3, Xcode 8.2.1, and iOS 10.2, on both an iPhone6 and an iPad Pro. Can't reproduce in the Simulator, or in a device with iOS 9.3.2. You can download a minimal sample app here: https://github.com/endavid/SwiftLeaks
Is this a known bug? Is there any work around?
Edit:
Because this remind me of another enum bug, Accessor gives the wrong value in Swift 1.2/2.0 Release build only, I tried making the enum an
@objc Int
enum, but it still leaks. However, makinglightingType
directly anInt
does fix the leak...Edit2: After updating my iPhone to 10.3 and Xcode to 8.3, the leak is gone. It seems it was an issue of iOS 10.2...
解决方案Hey @endavid managed to replicate the issue consistently. We spend a good time trying to figure out what was going on and your post helped a lot!
Here is the sample repo: https://github.com/Giphy/ios-memory-leak-sample
Radar: https://openradar.appspot.com/radar?id=4992108083544064
We are developing SDKs and same exact issue surfaced with a small difference. Since we wanted things to interop we added
@objc
to the enum definition and things started to leak exactly the way you described given your class has two properties, one enum and one mutable array.Consistently reproduced the leak:
// 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() } }
Work Around:
If we convert the optional enum class property to a non-optional, leak will disappear.
// Let's convert the optional property to a non-optional var leakyOptionalEnum: leakingObjCMarkedEnum = .orange
Edit:
It is fixed by guys @ Apple: https://bugs.swift.org/browse/SR-5625 PR: https://github.com/apple/swift/pull/11341
这篇关于当类包含数组时,Swift 3枚举泄漏内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!