【问题标题】:Where Singleton object is allocated?单例对象分配在哪里?
【发布时间】:2021-11-28 20:54:40
【问题描述】:
我想知道myClass对象的确切分配位置,所以我画了分配流程
class MyClass {
static let shared = MyClass()
private init() { }
}
let myClass = MyClass.shared
-
myClass 常量在堆栈中分配
-
myClass 常量指向分配MyClass 的堆
-
MyClass.shared 静态属性指向在堆中分配的MyClass()
这个流程对吗?我是不是误会了什么?
【问题讨论】:
标签:
swift
memory
singleton
allocation
【解决方案1】:
-
Swift 为数据段中的MyClass.shared 分配存储空间,初始化为 nil。数据段的布局和初始内容由可执行文件定义。从历史上看,堆在数据段的末尾立即开始,但在具有地址空间布局随机化 (ASLR) 的现代 64 位系统上,我不知道这是否仍然正确。
-
Swift还在数据段中分配了一个swift_once_t来记录MyClass.shared是否已经被初始化。
-
Swift 在代码段中为MyClass.shared 生成一个getter 函数。 getter 函数在第一次调用 getter 时使用swift_once_t 来初始化MyClass.shared 的存储。大概是这样的:
var _storage_MyClass_shared: MyClass? = nil
var _once_MyClass_shared: swift_once_t = .init() // essentially, false
func _getter_MyClass_shared() -> MyClass {
swift_once(&_once_MyClass_shared, {
_storage_MyClass_shared = MyClass()
})
return _storage_MyClass_shared!
}
-
MyClass 的实例存储在堆上。它以包含isa 指针(指向MyClass 元数据)的单词开头,然后是包含(通常)引用计数的单词,然后是对象实例变量的存储。在您的情况下,没有实例变量,因此没有额外的存储空间。图中标有Myclass() 的蓝色框和指向它的箭头不存在。
-
如果myClass 位于顶层(不在方法或数据类型声明中),那么它也会与另一个跟踪它是否已被初始化的swift_once_t 一起存储在数据段中,并且 Swift 会生成一个 getter在代码段中为它。
-
如果myClass 是一个数据类型的实例变量,那么它将作为其包含对象的一部分存储,该对象可能位于堆栈或堆上(在struct 的情况下,enum ,或元组)或始终在堆上(在class 或actor 的情况下)。
-
如果myClass 是函数中的局部变量,则将其存储在堆栈中。