iOS原理 AutoreleasePool的嵌套分析
2021-02-19 本文已影响0人
东篱采桑人
在iOS原理 AutoreleasePool的结构分析一文中分析了单个自动释放池的结构,本文将介绍AutoreleasePool
的嵌套情况。
//释放池嵌套
int main(int argc, char * argv[]) {
//pool1,里面添加1个自动释放对象
@autoreleasepool {
NSObject *obj = [[NSObject alloc] autorelease];
//pool2,里面添加3个自动释放对象
@autoreleasepool {
NSInteger count = 3;
for(NSInteger i=0; i<count; i++){
NSObject *obj = [[NSObject alloc] autorelease];
}
//pool3,里面添加2个自动释放对象
@autoreleasepool {
NSInteger count = 2;
for(NSInteger i=0; i<count; i++){
NSObject *obj = [[NSObject alloc] autorelease];
}
//创建完三个pool后打印
_objc_autoreleasePoolPrint();
}
//超出pool3的作用域时打印
_objc_autoreleasePoolPrint();
}
//超出pool2的作用域时打印
_objc_autoreleasePoolPrint();
}
//超出pool1作用域打印
_objc_autoreleasePoolPrint();
return 0;
}
如代码所示,在main
函数里嵌套创建了3个自动释放池,然后在不同时期打印内存结构。
创建后打印
objc[41194]: ##############
objc[41194]: AUTORELEASE POOLS for thread 0x114550dc0
objc[41194]: 9 releases pending.
objc[41194]: [0x7fe8e9815000] ................ PAGE (hot) (cold)
objc[41194]: [0x7fe8e9815038] ################ POOL 0x7fe8e9815038
objc[41194]: [0x7fe8e9815040] 0x600001c5c060 NSObject
objc[41194]: [0x7fe8e9815048] ################ POOL 0x7fe8e9815048
objc[41194]: [0x7fe8e9815050] 0x600001c5c070 NSObject
objc[41194]: [0x7fe8e9815058] 0x600001c5c080 NSObject
objc[41194]: [0x7fe8e9815060] 0x600001c5c090 NSObject
objc[41194]: [0x7fe8e9815068] ################ POOL 0x7fe8e9815068
objc[41194]: [0x7fe8e9815070] 0x600001c5c0a0 NSObject
objc[41194]: [0x7fe8e9815078] 0x600001c5c0b0 NSObject
objc[41194]: ##############
可以看到,线程里维护了一个自动释放池的堆栈。
- 第一个创建的
pool
为最外层释放池,当前只新建了一页page
。 - 嵌套创建的子
pool
在内存结构上来看,按顺序存于最外层释放池的page
中.
超出作用域时打印
//超出pool3
objc[41194]: ##############
objc[41194]: AUTORELEASE POOLS for thread 0x114550dc0
objc[41194]: 6 releases pending.
objc[41194]: [0x7fe8e9815000] ................ PAGE (hot) (cold)
objc[41194]: [0x7fe8e9815038] ################ POOL 0x7fe8e9815038
objc[41194]: [0x7fe8e9815040] 0x600001c5c060 NSObject
objc[41194]: [0x7fe8e9815048] ################ POOL 0x7fe8e9815048
objc[41194]: [0x7fe8e9815050] 0x600001c5c070 NSObject
objc[41194]: [0x7fe8e9815058] 0x600001c5c080 NSObject
objc[41194]: [0x7fe8e9815060] 0x600001c5c090 NSObject
objc[41194]: ##############
//超出pool2
objc[41194]: ##############
objc[41194]: AUTORELEASE POOLS for thread 0x114550dc0
objc[41194]: 2 releases pending.
objc[41194]: [0x7fe8e9815000] ................ PAGE (hot) (cold)
objc[41194]: [0x7fe8e9815038] ################ POOL 0x7fe8e9815038
objc[41194]: [0x7fe8e9815040] 0x600001c5c060 NSObject
objc[41194]: ##############
//超出pool1
objc[41194]: ##############
objc[41194]: AUTORELEASE POOLS for thread 0x114550dc0
objc[41194]: 0 releases pending.
objc[41194]: [0x7fe8e9815000] ................ PAGE (hot) (cold)
objc[41194]: ##############
从三次打印结果可知,虽然子pool
按顺序存在最外层释放池的page
中,但每个pool
还是各自管理自己的自动释放对象。
- 当超出子
pool
的作用域时,子pool
会被销毁,里面的对象也都会被释放。 - 当超出最外层
pool
的作用域时,里面的对象会被释放,但释放池不会被销毁,会保留一个空白的page
。 - 每个线程都会维护自身的自动释放池堆栈,只有当线程被销毁时,最外层
pool
才会被销毁。