iOS-内存管理分析(下)
前言
iOS-内存管理分析(上)以及iOS-内存管理分析(中)分析了内存的分区,布局,散列表,弱引用计数表等相关知识,这篇文章继续分析内存管理。
1 自动释放池初探
在我们的demo工程的main文件代码如下
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
}
return 0;
}
我们通过clang命令,看下底层,我们在main.cpp找到如下代码
int main(int argc, const char * argv[]) {
/* */ { __AtAutoreleasePool __autoreleasepool;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_r7_rnm6hs1x2jg8bqy7sjwsskx00000gn_T_main_1cecfd_mi_0);
}
return 0;
}
@autoreleasepool被注释了,替换的是*__AtAutoreleasePool __autoreleasepool; *这个。
__AtAutoreleasePool是一个结构体,如下
struct __AtAutoreleasePool {
__AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}
~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}
void * atautoreleasepoolobj;
};
这里有一个构造和析构函数,构造函数创建一个objc_autoreleasePoolPush对象,释构函数调用objc_autoreleasePoolPop释入这个objc_autoreleasePoolPush对象。
当然我们还可以通过汇编分析流程,这里不再叙述。
2 自动释放池结构
objc_autoreleasePoolPush与objc_autoreleasePoolPop的底层到底是什么,做了什么操作,我们接下来分析下。
我们在objc(818)的源码中搜索下objc_autoreleasePoolPush这个函数,找到如下代码
void *
objc_autoreleasePoolPush(void)
{
return AutoreleasePoolPage::push();
}
调用了AutoreleasePoolPage它的push()函数,我们进去看下,如下
class AutoreleasePoolPage : private AutoreleasePoolPageData
AutoreleasePoolPage继承于AutoreleasePoolPageData。
Autorelease pool implementation
A thread's autorelease pool is a stack of pointers.
Each pointer is either an object to release, or POOL_BOUNDARY which is
an autorelease pool boundary.
A pool token is a pointer to the POOL_BOUNDARY for that pool. When
the pool is popped, every object hotter than the sentinel is released.
The stack is divided into a doubly-linked list of pages. Pages are added
and deleted as necessary.
Thread-local storage points to the hot page, where newly autoreleased
objects are stored.
自动释放池与线程有关联的。POOL_BOUNDARY就是哨兵对象边(自动释放池边界),不能无限制出栈,如果没有这个边界,不断的出栈,会出现访问野指针。
这里说了自动释放池是一个双向链表。
我们再来看下AutoreleasePoolPageData
struct AutoreleasePoolPageData
{
#if SUPPORT_AUTORELEASEPOOL_DEDUP_PTRS
struct AutoreleasePoolEntry {
uintptr_t ptr: 48;
uintptr_t count: 16;
static const uintptr_t maxCount = 65535; // 2^16 - 1
};
static_assert((AutoreleasePoolEntry){ .ptr = MACH_VM_MAX_ADDRESS }.ptr == MACH_VM_MAX_ADDRESS, "MACH_VM_MAX_ADDRESS doesn't fit into AutoreleasePoolEntry::ptr!");
#endif
magic_t const magic; // 16
__unsafe_unretained id *next; // 8
pthread_t const thread; // 8
AutoreleasePoolPage * const parent; // 8
AutoreleasePoolPage *child; // 8
uint32_t const depth; // 4
uint32_t hiwat; // 4
AutoreleasePoolPageData(__unsafe_unretained id* _next, pthread_t _thread, AutoreleasePoolPage* _parent, uint32_t _depth, uint32_t _hiwat)
: magic(), next(_next), thread(_thread),
parent(_parent), child(nil),
depth(_depth), hiwat(_hiwat)
{
}
};
- magic⽤来校验AutoreleasePoolPage的结构是否完整;
- next指向最新添加的autoreleased对象的下⼀个位置,初始化时指向begin();
- thread指向当前线程;
- parent指向⽗结点,第⼀个结点的parent值为nil;
- child指向⼦结点,最后⼀个结点的child值为nil;
- depth代表深度,从0开始,往后递增1;
- hiwat代表highwatermark最⼤⼊栈数量标记
我们改下main.m源码,压栈一个对象,
#import <Foundation/Foundation.h>
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *objc = [[[NSObject alloc] init] autorelease];
_objc_autoreleasePoolPrint();
}
return 0;
}
这里一定要把arc关掉。
运行项目,如下
objc[27889]: AUTORELEASE POOLS for thread 0x1000ebe00
objc[27889]: 2 releases pending.
objc[27889]: [0x10200c000] ................ PAGE (hot) (cold)
objc[27889]: [0x10200c038] ################ POOL 0x10200c038
objc[27889]: [0x10200c040] 0x10060dfc0 NSObject
objc[27889]: ##############
Program ended with exit code: 0
这里可以看到NSObject对象是压入栈了。
这里有两个对象的原因,是因为哨兵对象也是一个对象。
3 自动释放池的创建和压栈
自动释放池的创建和压栈是如何进行的,我们分析它的源码看下。
我们看下AutoreleasePoolPage::push();的源码,如下
static inline void *push()
{
id *dest;
if (slowpath(DebugPoolAllocation)) {
// Each autorelease pool starts on a new pool page.
dest = autoreleaseNewPage(POOL_BOUNDARY);
} else {
dest = autoreleaseFast(POOL_BOUNDARY);
}
ASSERT(dest == EMPTY_POOL_PLACEHOLDER || *dest == POOL_BOUNDARY);
return dest;
}
我们再来看下autoreleaseFast这个函数,源码如下
static inline id *autoreleaseFast(id obj)
{
AutoreleasePoolPage *page = hotPage();
if (page && !page->full()) {
return page->add(obj);
} else if (page) {
return autoreleaseFullPage(obj, page);
} else {
return autoreleaseNoPage(obj);
}
}
这里判断页面是否存在并且没有满,直接add进去。
如果满了调用autoreleaseFullPage处理,如果没有这个页面,调用autoreleaseNoPage创建。
我们再来看下autoreleaseNoPage,如下
static __attribute__((noinline))
id *autoreleaseNoPage(id obj)
{
// "No page" could mean no pool has been pushed
// or an empty placeholder pool has been pushed and has no contents yet
ASSERT(!hotPage());
bool pushExtraBoundary = false;
if (haveEmptyPoolPlaceholder()) {
// We are pushing a second pool over the empty placeholder pool
// or pushing the first object into the empty placeholder pool.
// Before doing that, push a pool boundary on behalf of the pool
// that is currently represented by the empty placeholder.
pushExtraBoundary = true;
}
else if (obj != POOL_BOUNDARY && DebugMissingPools) {
// We are pushing an object with no pool in place,
// and no-pool debugging was requested by environment.
_objc_inform("MISSING POOLS: (%p) Object %p of class %s "
"autoreleased with no pool in place - "
"just leaking - break on "
"objc_autoreleaseNoPool() to debug",
objc_thread_self(), (void*)obj, object_getClassName(obj));
objc_autoreleaseNoPool(obj);
return nil;
}
else if (obj == POOL_BOUNDARY && !DebugPoolAllocation) {
// We are pushing a pool with no pool in place,
// and alloc-per-pool debugging was not requested.
// Install and return the empty pool placeholder.
return setEmptyPoolPlaceholder();
}
// We are pushing an object or a non-placeholder'd pool.
// Install the first page.
AutoreleasePoolPage *page = new AutoreleasePoolPage(nil);
setHotPage(page);
// Push a boundary on behalf of the previously-placeholder'd pool.
if (pushExtraBoundary) {
page->add(POOL_BOUNDARY);
}
// Push the requested object or pool.
return page->add(obj);
}
在这里
AutoreleasePoolPage *page = new AutoreleasePoolPage(nil);
setHotPage(page);
创建新页面,并设置成hot页面,之后再add对象
我们再看下AutoreleasePoolPage
AutoreleasePoolPage(AutoreleasePoolPage *newParent) :
AutoreleasePoolPageData(begin(),
objc_thread_self(),
newParent,
newParent ? 1+newParent->depth : 0,
newParent ? newParent->hiwat : 0)
{
if (objc::PageCountWarning != -1) {
checkTooMuchAutorelease();
}
if (parent) {
parent->check();
ASSERT(!parent->child);
parent->unprotect();
parent->child = this;
parent->protect();
}
protect();
}
这里设置双向链表的数据。
我们看下的begin如下
id * begin() {
return (id *) ((uint8_t *)this+sizeof(*this));
}
sizeof(*this)这时56的大小,来源于autorealeaPoolDat成员变量
magic_t const magic;//16
__unsafe_unretained id *next;//8
pthread_t const thread; //8
AutoreleasePoolPage * const parent; //8
AutoreleasePoolPage *child; //8
uint32_t const depth;//4
uint32_t hiwat;//4
magic_t是结构体,有一个uint32_4 m[4]占用16字节。
objc_thread_self(),获取当前线程。
自动释放池的成员变量也是占用空间的。
POOL 0x10080c038上方的这个是我们的哨兵对象。
4 自动释放池的满页临界和压栈出栈
当我们的页面满的时候,是如何处理的,结构又有什么变化呢,我们继续分析下源码才能得到。
我们知道内存是分页的加载的,为什么这么做呢?
假如不分页的话会出现以下情况
- 不断的压栈出栈,会对这张表操作非常频繁,也就是说对内存操作频繁
- 压栈出栈的时候,会对整张表进行加锁解锁,非常消耗性能
- 所有的对象存在这张表,非常复杂,管理复杂
- 如果某个局部发生问题,整张表都会影响
而分页的方式就不会有这些问题
内存分页的好处 - 内存可以不连续
- 性能大大的提高
我们一张表可以存放多少内存, 我们探索一下。
我们在改下我们的main.m文件
#import <Foundation/Foundation.h>
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
for (int i = 0; i<4; i++) {
NSObject *objc = [[[NSObject alloc] init] autorelease];
}
_objc_autoreleasePoolPrint();
}
return 0;
}
我们运行项目,看下效果,如下所示
objc[29930]: AUTORELEASE POOLS for thread 0x1000ebe00
objc[29930]: 5 releases pending.
objc[29930]: [0x101009000] ................ PAGE (hot) (cold)
objc[29930]: [0x101009038] ################ POOL 0x101009038
objc[29930]: [0x101009040] 0x101a4b020 NSObject
objc[29930]: [0x101009048] 0x101a3f2d0 NSObject
objc[29930]: [0x101009050] 0x101a3ebf0 NSObject
objc[29930]: [0x101009058] 0x101a3dac0 NSObject
objc[29930]: ##############
KCObjcBuild was compiled with optimization - stepping may behave oddly; variables may not be available.
我们可以看到没有产生分页的效果,我们再把循环改下505,再看下效果
objc[29984]: AUTORELEASE POOLS for thread 0x1000ebe00
objc[29984]: 506 releases pending.
objc[29984]: [0x10480d000] ................ PAGE (full) (cold)
objc[29984]: [0x10480d038] ################ POOL 0x10480d038
objc[29984]: [0x10480d040] 0x10132a9f0 NSObject
objc[29984]: [0x10480d048] 0x101328f20 NSObject
objc[29984]: [0x10480d050] 0x101328b70 NSObject
objc[29984]: [0x10480d058] 0x101328bd0 NSObject
objc[29984]: [0x10480d060] 0x101327b10 NSObject
objc[29984]: [0x10480d068] 0x101327b50 NSObject
objc[29984]: [0x10480d070] 0x101327100 NSObject
objc[29984]: [0x10480d078] 0x101325fd0 NSObject
objc[29984]: [0x10480d080] 0x101326010 NSObject
objc[29984]: [0x10480d088] 0x101326040 NSObject
objc[29984]: [0x10480d090] 0x101325ae0 NSObject
objc[29984]: [0x10480d098] 0x101324fc0 NSObject
objc[29984]: [0x10480d0a0] 0x1013249a0 NSObject
objc[29984]: [0x10480d0a8] 0x101324500 NSObject
objc[29984]: [0x10480d0b0] 0x101323ff0 NSObject
objc[29984]: [0x10480d0b8] 0x101323290 NSObject
objc[29984]: [0x10480d0c0] 0x101322d90 NSObject
objc[29984]: [0x10480d0c8] 0x101322630 NSObject
objc[29984]: [0x10480d0d0] 0x101322660 NSObject
objc[29984]: [0x10480d0d8] 0x10130f190 NSObject
objc[29984]: [0x10480d0e0] 0x10130f1c0 NSObject
objc[29984]: [0x10480d0e8] 0x10130e510 NSObject
objc[29984]: [0x10480d0f0] 0x10130e7d0 NSObject
objc[29984]: [0x10480d0f8] 0x10130d7b0 NSObject
objc[29984]: [0x10480d100] 0x10130d080 NSObject
objc[29984]: [0x10480d108] 0x10130d140 NSObject
objc[29984]: [0x10480d110] 0x10130be70 NSObject
objc[29984]: [0x10480d118] 0x10130ade0 NSObject
objc[29984]: [0x10480d120] 0x10130a1b0 NSObject
objc[29984]: [0x10480d128] 0x101305530 NSObject
objc[29984]: [0x10480d130] 0x101308ca0 NSObject
objc[29984]: [0x10480d138] 0x101308e60 NSObject
objc[29984]: [0x10480d140] 0x101304900 NSObject
objc[29984]: [0x10480d148] 0x1013387a0 NSObject
objc[29984]: [0x10480d150] 0x1013387b0 NSObject
objc[29984]: [0x10480d158] 0x1013387c0 NSObject
objc[29984]: [0x10480d160] 0x1013387d0 NSObject
objc[29984]: [0x10480d168] 0x1013387e0 NSObject
objc[29984]: [0x10480d170] 0x1013387f0 NSObject
objc[29984]: [0x10480d178] 0x101338800 NSObject
objc[29984]: [0x10480d180] 0x101338810 NSObject
objc[29984]: [0x10480d188] 0x101338820 NSObject
objc[29984]: [0x10480d190] 0x101338830 NSObject
objc[29984]: [0x10480d198] 0x101338840 NSObject
objc[29984]: [0x10480d1a0] 0x101338850 NSObject
objc[29984]: [0x10480d1a8] 0x101338860 NSObject
objc[29984]: [0x10480d1b0] 0x101338870 NSObject
objc[29984]: [0x10480d1b8] 0x101338880 NSObject
objc[29984]: [0x10480d1c0] 0x101338890 NSObject
objc[29984]: [0x10480d1c8] 0x101338bb0 NSObject
objc[29984]: [0x10480d1d0] 0x101338bc0 NSObject
objc[29984]: [0x10480d1d8] 0x101338bd0 NSObject
objc[29984]: [0x10480d1e0] 0x101338be0 NSObject
objc[29984]: [0x10480d1e8] 0x101338bf0 NSObject
objc[29984]: [0x10480d1f0] 0x101338c00 NSObject
objc[29984]: [0x10480d1f8] 0x101338c10 NSObject
objc[29984]: [0x10480d200] 0x101338c20 NSObject
objc[29984]: [0x10480d208] 0x101338c30 NSObject
objc[29984]: [0x10480d210] 0x101338c40 NSObject
objc[29984]: [0x10480d218] 0x101338c50 NSObject
objc[29984]: [0x10480d220] 0x101338c60 NSObject
objc[29984]: [0x10480d228] 0x101338c70 NSObject
objc[29984]: [0x10480d230] 0x101338c80 NSObject
objc[29984]: [0x10480d238] 0x101338c90 NSObject
objc[29984]: [0x10480d240] 0x101338ca0 NSObject
objc[29984]: [0x10480d248] 0x101338cb0 NSObject
objc[29984]: [0x10480d250] 0x101338cc0 NSObject
objc[29984]: [0x10480d258] 0x101338cd0 NSObject
objc[29984]: [0x10480d260] 0x101338ce0 NSObject
objc[29984]: [0x10480d268] 0x101338cf0 NSObject
objc[29984]: [0x10480d270] 0x101338d00 NSObject
objc[29984]: [0x10480d278] 0x101338d10 NSObject
objc[29984]: [0x10480d280] 0x101338d20 NSObject
objc[29984]: [0x10480d288] 0x101338d30 NSObject
objc[29984]: [0x10480d290] 0x101338d40 NSObject
objc[29984]: [0x10480d298] 0x101338d50 NSObject
objc[29984]: [0x10480d2a0] 0x101338d60 NSObject
objc[29984]: [0x10480d2a8] 0x101338d70 NSObject
objc[29984]: [0x10480d2b0] 0x101338d80 NSObject
objc[29984]: [0x10480d2b8] 0x101338d90 NSObject
objc[29984]: [0x10480d2c0] 0x101338da0 NSObject
objc[29984]: [0x10480d2c8] 0x101338db0 NSObject
objc[29984]: [0x10480d2d0] 0x101338dc0 NSObject
objc[29984]: [0x10480d2d8] 0x101338dd0 NSObject
objc[29984]: [0x10480d2e0] 0x101338de0 NSObject
objc[29984]: [0x10480d2e8] 0x101338df0 NSObject
objc[29984]: [0x10480d2f0] 0x101338e00 NSObject
objc[29984]: [0x10480d2f8] 0x101338e10 NSObject
objc[29984]: [0x10480d300] 0x101338e20 NSObject
objc[29984]: [0x10480d308] 0x101338e30 NSObject
objc[29984]: [0x10480d310] 0x101338e40 NSObject
objc[29984]: [0x10480d318] 0x101338e50 NSObject
objc[29984]: [0x10480d320] 0x101338e60 NSObject
objc[29984]: [0x10480d328] 0x101338e70 NSObject
objc[29984]: [0x10480d330] 0x101338e80 NSObject
objc[29984]: [0x10480d338] 0x101338e90 NSObject
objc[29984]: [0x10480d340] 0x101338ea0 NSObject
objc[29984]: [0x10480d348] 0x101338eb0 NSObject
objc[29984]: [0x10480d350] 0x101338ec0 NSObject
objc[29984]: [0x10480d358] 0x101338ed0 NSObject
objc[29984]: [0x10480d360] 0x101338ee0 NSObject
objc[29984]: [0x10480d368] 0x101338ef0 NSObject
objc[29984]: [0x10480d370] 0x101338f00 NSObject
objc[29984]: [0x10480d378] 0x101338f10 NSObject
objc[29984]: [0x10480d380] 0x101338f20 NSObject
objc[29984]: [0x10480d388] 0x101338f30 NSObject
objc[29984]: [0x10480d390] 0x101338f40 NSObject
objc[29984]: [0x10480d398] 0x101338f50 NSObject
objc[29984]: [0x10480d3a0] 0x101338f60 NSObject
objc[29984]: [0x10480d3a8] 0x101338f70 NSObject
objc[29984]: [0x10480d3b0] 0x101338f80 NSObject
objc[29984]: [0x10480d3b8] 0x101338f90 NSObject
objc[29984]: [0x10480d3c0] 0x101338fa0 NSObject
objc[29984]: [0x10480d3c8] 0x101338fb0 NSObject
objc[29984]: [0x10480d3d0] 0x101338fc0 NSObject
objc[29984]: [0x10480d3d8] 0x101338fd0 NSObject
objc[29984]: [0x10480d3e0] 0x101338fe0 NSObject
objc[29984]: [0x10480d3e8] 0x101338ff0 NSObject
objc[29984]: [0x10480d3f0] 0x101339000 NSObject
objc[29984]: [0x10480d3f8] 0x101339010 NSObject
objc[29984]: [0x10480d400] 0x101339020 NSObject
objc[29984]: [0x10480d408] 0x101339030 NSObject
objc[29984]: [0x10480d410] 0x101339040 NSObject
objc[29984]: [0x10480d418] 0x101339050 NSObject
objc[29984]: [0x10480d420] 0x101339060 NSObject
objc[29984]: [0x10480d428] 0x101339070 NSObject
objc[29984]: [0x10480d430] 0x101339080 NSObject
objc[29984]: [0x10480d438] 0x101339090 NSObject
objc[29984]: [0x10480d440] 0x1013390a0 NSObject
objc[29984]: [0x10480d448] 0x1013390b0 NSObject
objc[29984]: [0x10480d450] 0x1013390c0 NSObject
objc[29984]: [0x10480d458] 0x1013390d0 NSObject
objc[29984]: [0x10480d460] 0x1013390e0 NSObject
objc[29984]: [0x10480d468] 0x1013390f0 NSObject
objc[29984]: [0x10480d470] 0x101339100 NSObject
objc[29984]: [0x10480d478] 0x101339110 NSObject
objc[29984]: [0x10480d480] 0x101339120 NSObject
objc[29984]: [0x10480d488] 0x101339130 NSObject
objc[29984]: [0x10480d490] 0x101339140 NSObject
objc[29984]: [0x10480d498] 0x101339150 NSObject
objc[29984]: [0x10480d4a0] 0x101339160 NSObject
objc[29984]: [0x10480d4a8] 0x101339170 NSObject
objc[29984]: [0x10480d4b0] 0x101339180 NSObject
objc[29984]: [0x10480d4b8] 0x101339190 NSObject
objc[29984]: [0x10480d4c0] 0x1013391a0 NSObject
objc[29984]: [0x10480d4c8] 0x1013391b0 NSObject
objc[29984]: [0x10480d4d0] 0x1013391c0 NSObject
objc[29984]: [0x10480d4d8] 0x1013391d0 NSObject
objc[29984]: [0x10480d4e0] 0x1013391e0 NSObject
objc[29984]: [0x10480d4e8] 0x1013391f0 NSObject
objc[29984]: [0x10480d4f0] 0x101339200 NSObject
objc[29984]: [0x10480d4f8] 0x101339210 NSObject
objc[29984]: [0x10480d500] 0x101339220 NSObject
objc[29984]: [0x10480d508] 0x101339230 NSObject
objc[29984]: [0x10480d510] 0x101339240 NSObject
objc[29984]: [0x10480d518] 0x101339250 NSObject
objc[29984]: [0x10480d520] 0x101339260 NSObject
objc[29984]: [0x10480d528] 0x101339270 NSObject
objc[29984]: [0x10480d530] 0x101339280 NSObject
objc[29984]: [0x10480d538] 0x101339290 NSObject
objc[29984]: [0x10480d540] 0x1013392a0 NSObject
objc[29984]: [0x10480d548] 0x1013392b0 NSObject
objc[29984]: [0x10480d550] 0x1013392c0 NSObject
objc[29984]: [0x10480d558] 0x1013392d0 NSObject
objc[29984]: [0x10480d560] 0x1013392e0 NSObject
objc[29984]: [0x10480d568] 0x1013392f0 NSObject
objc[29984]: [0x10480d570] 0x101339300 NSObject
objc[29984]: [0x10480d578] 0x101339310 NSObject
objc[29984]: [0x10480d580] 0x101339320 NSObject
objc[29984]: [0x10480d588] 0x101339330 NSObject
objc[29984]: [0x10480d590] 0x101339340 NSObject
objc[29984]: [0x10480d598] 0x101339350 NSObject
objc[29984]: [0x10480d5a0] 0x101339360 NSObject
objc[29984]: [0x10480d5a8] 0x101339370 NSObject
objc[29984]: [0x10480d5b0] 0x101339380 NSObject
objc[29984]: [0x10480d5b8] 0x101339390 NSObject
objc[29984]: [0x10480d5c0] 0x1013393a0 NSObject
objc[29984]: [0x10480d5c8] 0x1013393b0 NSObject
objc[29984]: [0x10480d5d0] 0x1013393c0 NSObject
objc[29984]: [0x10480d5d8] 0x1013393d0 NSObject
objc[29984]: [0x10480d5e0] 0x1013393e0 NSObject
objc[29984]: [0x10480d5e8] 0x1013393f0 NSObject
objc[29984]: [0x10480d5f0] 0x101339400 NSObject
objc[29984]: [0x10480d5f8] 0x101339410 NSObject
objc[29984]: [0x10480d600] 0x101339420 NSObject
objc[29984]: [0x10480d608] 0x101339430 NSObject
objc[29984]: [0x10480d610] 0x101339440 NSObject
objc[29984]: [0x10480d618] 0x101339450 NSObject
objc[29984]: [0x10480d620] 0x101339460 NSObject
objc[29984]: [0x10480d628] 0x101339470 NSObject
objc[29984]: [0x10480d630] 0x101339480 NSObject
objc[29984]: [0x10480d638] 0x101339490 NSObject
objc[29984]: [0x10480d640] 0x1013394a0 NSObject
objc[29984]: [0x10480d648] 0x1013394b0 NSObject
objc[29984]: [0x10480d650] 0x1013394c0 NSObject
objc[29984]: [0x10480d658] 0x1013394d0 NSObject
objc[29984]: [0x10480d660] 0x1013394e0 NSObject
objc[29984]: [0x10480d668] 0x1013394f0 NSObject
objc[29984]: [0x10480d670] 0x101339500 NSObject
objc[29984]: [0x10480d678] 0x101339510 NSObject
objc[29984]: [0x10480d680] 0x101339520 NSObject
objc[29984]: [0x10480d688] 0x101339530 NSObject
objc[29984]: [0x10480d690] 0x101339540 NSObject
objc[29984]: [0x10480d698] 0x101339550 NSObject
objc[29984]: [0x10480d6a0] 0x101339560 NSObject
objc[29984]: [0x10480d6a8] 0x101339570 NSObject
objc[29984]: [0x10480d6b0] 0x101339580 NSObject
objc[29984]: [0x10480d6b8] 0x101339590 NSObject
objc[29984]: [0x10480d6c0] 0x1013395a0 NSObject
objc[29984]: [0x10480d6c8] 0x1013395b0 NSObject
objc[29984]: [0x10480d6d0] 0x1013395c0 NSObject
objc[29984]: [0x10480d6d8] 0x1013395d0 NSObject
objc[29984]: [0x10480d6e0] 0x1013395e0 NSObject
objc[29984]: [0x10480d6e8] 0x1013395f0 NSObject
objc[29984]: [0x10480d6f0] 0x101339600 NSObject
objc[29984]: [0x10480d6f8] 0x101339610 NSObject
objc[29984]: [0x10480d700] 0x101339620 NSObject
objc[29984]: [0x10480d708] 0x101339630 NSObject
objc[29984]: [0x10480d710] 0x101339640 NSObject
objc[29984]: [0x10480d718] 0x101339650 NSObject
objc[29984]: [0x10480d720] 0x101339660 NSObject
objc[29984]: [0x10480d728] 0x101339670 NSObject
objc[29984]: [0x10480d730] 0x101339680 NSObject
objc[29984]: [0x10480d738] 0x101339690 NSObject
objc[29984]: [0x10480d740] 0x1013396a0 NSObject
objc[29984]: [0x10480d748] 0x1013396b0 NSObject
objc[29984]: [0x10480d750] 0x1013396c0 NSObject
objc[29984]: [0x10480d758] 0x1013396d0 NSObject
objc[29984]: [0x10480d760] 0x1013396e0 NSObject
objc[29984]: [0x10480d768] 0x1013396f0 NSObject
objc[29984]: [0x10480d770] 0x101339700 NSObject
objc[29984]: [0x10480d778] 0x101339710 NSObject
objc[29984]: [0x10480d780] 0x101339720 NSObject
objc[29984]: [0x10480d788] 0x101339730 NSObject
objc[29984]: [0x10480d790] 0x101339740 NSObject
objc[29984]: [0x10480d798] 0x101339750 NSObject
objc[29984]: [0x10480d7a0] 0x101339760 NSObject
objc[29984]: [0x10480d7a8] 0x101339770 NSObject
objc[29984]: [0x10480d7b0] 0x101339780 NSObject
objc[29984]: [0x10480d7b8] 0x101339790 NSObject
objc[29984]: [0x10480d7c0] 0x1013397a0 NSObject
objc[29984]: [0x10480d7c8] 0x1013397b0 NSObject
objc[29984]: [0x10480d7d0] 0x1013397c0 NSObject
objc[29984]: [0x10480d7d8] 0x1013397d0 NSObject
objc[29984]: [0x10480d7e0] 0x1013397e0 NSObject
objc[29984]: [0x10480d7e8] 0x1013397f0 NSObject
objc[29984]: [0x10480d7f0] 0x101339800 NSObject
objc[29984]: [0x10480d7f8] 0x101339810 NSObject
objc[29984]: [0x10480d800] 0x101339820 NSObject
objc[29984]: [0x10480d808] 0x101339830 NSObject
objc[29984]: [0x10480d810] 0x101339840 NSObject
objc[29984]: [0x10480d818] 0x101339850 NSObject
objc[29984]: [0x10480d820] 0x101339860 NSObject
objc[29984]: [0x10480d828] 0x101339870 NSObject
objc[29984]: [0x10480d830] 0x101339880 NSObject
objc[29984]: [0x10480d838] 0x101339890 NSObject
objc[29984]: [0x10480d840] 0x1013398a0 NSObject
objc[29984]: [0x10480d848] 0x1013398b0 NSObject
objc[29984]: [0x10480d850] 0x1013398c0 NSObject
objc[29984]: [0x10480d858] 0x1013398d0 NSObject
objc[29984]: [0x10480d860] 0x1013398e0 NSObject
objc[29984]: [0x10480d868] 0x1013398f0 NSObject
objc[29984]: [0x10480d870] 0x101339900 NSObject
objc[29984]: [0x10480d878] 0x101339910 NSObject
objc[29984]: [0x10480d880] 0x101339920 NSObject
objc[29984]: [0x10480d888] 0x101339930 NSObject
objc[29984]: [0x10480d890] 0x101339940 NSObject
objc[29984]: [0x10480d898] 0x101339950 NSObject
objc[29984]: [0x10480d8a0] 0x101339960 NSObject
objc[29984]: [0x10480d8a8] 0x101339970 NSObject
objc[29984]: [0x10480d8b0] 0x101339980 NSObject
objc[29984]: [0x10480d8b8] 0x101339990 NSObject
objc[29984]: [0x10480d8c0] 0x1013399a0 NSObject
objc[29984]: [0x10480d8c8] 0x1013399b0 NSObject
objc[29984]: [0x10480d8d0] 0x1013399c0 NSObject
objc[29984]: [0x10480d8d8] 0x1013399d0 NSObject
objc[29984]: [0x10480d8e0] 0x1013399e0 NSObject
objc[29984]: [0x10480d8e8] 0x1013399f0 NSObject
objc[29984]: [0x10480d8f0] 0x101339a00 NSObject
objc[29984]: [0x10480d8f8] 0x101339a10 NSObject
objc[29984]: [0x10480d900] 0x101339a20 NSObject
objc[29984]: [0x10480d908] 0x101339a30 NSObject
objc[29984]: [0x10480d910] 0x101339a40 NSObject
objc[29984]: [0x10480d918] 0x101339a50 NSObject
objc[29984]: [0x10480d920] 0x101339a60 NSObject
objc[29984]: [0x10480d928] 0x101339a70 NSObject
objc[29984]: [0x10480d930] 0x101339a80 NSObject
objc[29984]: [0x10480d938] 0x101339a90 NSObject
objc[29984]: [0x10480d940] 0x101339aa0 NSObject
objc[29984]: [0x10480d948] 0x101339ab0 NSObject
objc[29984]: [0x10480d950] 0x101339ac0 NSObject
objc[29984]: [0x10480d958] 0x101339ad0 NSObject
objc[29984]: [0x10480d960] 0x101339ae0 NSObject
objc[29984]: [0x10480d968] 0x101339af0 NSObject
objc[29984]: [0x10480d970] 0x101339b00 NSObject
objc[29984]: [0x10480d978] 0x101339b10 NSObject
objc[29984]: [0x10480d980] 0x101339b20 NSObject
objc[29984]: [0x10480d988] 0x101339b30 NSObject
objc[29984]: [0x10480d990] 0x101339b40 NSObject
objc[29984]: [0x10480d998] 0x101339b50 NSObject
objc[29984]: [0x10480d9a0] 0x101339b60 NSObject
objc[29984]: [0x10480d9a8] 0x101339b70 NSObject
objc[29984]: [0x10480d9b0] 0x101339b80 NSObject
objc[29984]: [0x10480d9b8] 0x101339b90 NSObject
objc[29984]: [0x10480d9c0] 0x101339ba0 NSObject
objc[29984]: [0x10480d9c8] 0x101339bb0 NSObject
objc[29984]: [0x10480d9d0] 0x101339bc0 NSObject
objc[29984]: [0x10480d9d8] 0x101339bd0 NSObject
objc[29984]: [0x10480d9e0] 0x101339be0 NSObject
objc[29984]: [0x10480d9e8] 0x101339bf0 NSObject
objc[29984]: [0x10480d9f0] 0x101339c00 NSObject
objc[29984]: [0x10480d9f8] 0x101339c10 NSObject
objc[29984]: [0x10480da00] 0x101339c20 NSObject
objc[29984]: [0x10480da08] 0x101339c30 NSObject
objc[29984]: [0x10480da10] 0x101339c40 NSObject
objc[29984]: [0x10480da18] 0x101339c50 NSObject
objc[29984]: [0x10480da20] 0x101339c60 NSObject
objc[29984]: [0x10480da28] 0x101339c70 NSObject
objc[29984]: [0x10480da30] 0x101339c80 NSObject
objc[29984]: [0x10480da38] 0x101339c90 NSObject
objc[29984]: [0x10480da40] 0x101339ca0 NSObject
objc[29984]: [0x10480da48] 0x101339cb0 NSObject
objc[29984]: [0x10480da50] 0x101339cc0 NSObject
objc[29984]: [0x10480da58] 0x101339cd0 NSObject
objc[29984]: [0x10480da60] 0x101339ce0 NSObject
objc[29984]: [0x10480da68] 0x101339cf0 NSObject
objc[29984]: [0x10480da70] 0x101339d00 NSObject
objc[29984]: [0x10480da78] 0x101339d10 NSObject
objc[29984]: [0x10480da80] 0x101339d20 NSObject
objc[29984]: [0x10480da88] 0x101339d30 NSObject
objc[29984]: [0x10480da90] 0x101339d40 NSObject
objc[29984]: [0x10480da98] 0x101339d50 NSObject
objc[29984]: [0x10480daa0] 0x101339d60 NSObject
objc[29984]: [0x10480daa8] 0x101339d70 NSObject
objc[29984]: [0x10480dab0] 0x101339d80 NSObject
objc[29984]: [0x10480dab8] 0x101339d90 NSObject
objc[29984]: [0x10480dac0] 0x101339da0 NSObject
objc[29984]: [0x10480dac8] 0x101339db0 NSObject
objc[29984]: [0x10480dad0] 0x101339dc0 NSObject
objc[29984]: [0x10480dad8] 0x101339dd0 NSObject
objc[29984]: [0x10480dae0] 0x101339de0 NSObject
objc[29984]: [0x10480dae8] 0x101339df0 NSObject
objc[29984]: [0x10480daf0] 0x101339e00 NSObject
objc[29984]: [0x10480daf8] 0x101339e10 NSObject
objc[29984]: [0x10480db00] 0x101339e20 NSObject
objc[29984]: [0x10480db08] 0x101339e30 NSObject
objc[29984]: [0x10480db10] 0x101339e40 NSObject
objc[29984]: [0x10480db18] 0x101339e50 NSObject
objc[29984]: [0x10480db20] 0x101339e60 NSObject
objc[29984]: [0x10480db28] 0x101339e70 NSObject
objc[29984]: [0x10480db30] 0x101339e80 NSObject
objc[29984]: [0x10480db38] 0x101339e90 NSObject
objc[29984]: [0x10480db40] 0x101339ea0 NSObject
objc[29984]: [0x10480db48] 0x101339eb0 NSObject
objc[29984]: [0x10480db50] 0x101339ec0 NSObject
objc[29984]: [0x10480db58] 0x101339ed0 NSObject
objc[29984]: [0x10480db60] 0x101339ee0 NSObject
objc[29984]: [0x10480db68] 0x101339ef0 NSObject
objc[29984]: [0x10480db70] 0x101339f00 NSObject
objc[29984]: [0x10480db78] 0x101339f10 NSObject
objc[29984]: [0x10480db80] 0x101339f20 NSObject
objc[29984]: [0x10480db88] 0x101339f30 NSObject
objc[29984]: [0x10480db90] 0x101339f40 NSObject
objc[29984]: [0x10480db98] 0x101339f50 NSObject
objc[29984]: [0x10480dba0] 0x101339f60 NSObject
objc[29984]: [0x10480dba8] 0x101339f70 NSObject
objc[29984]: [0x10480dbb0] 0x101339f80 NSObject
objc[29984]: [0x10480dbb8] 0x101339f90 NSObject
objc[29984]: [0x10480dbc0] 0x101339fa0 NSObject
objc[29984]: [0x10480dbc8] 0x101339fb0 NSObject
objc[29984]: [0x10480dbd0] 0x101339fc0 NSObject
objc[29984]: [0x10480dbd8] 0x101339fd0 NSObject
objc[29984]: [0x10480dbe0] 0x101339fe0 NSObject
objc[29984]: [0x10480dbe8] 0x101339ff0 NSObject
objc[29984]: [0x10480dbf0] 0x10133a000 NSObject
objc[29984]: [0x10480dbf8] 0x10133a010 NSObject
objc[29984]: [0x10480dc00] 0x10133a020 NSObject
objc[29984]: [0x10480dc08] 0x10133a030 NSObject
objc[29984]: [0x10480dc10] 0x10133a040 NSObject
objc[29984]: [0x10480dc18] 0x10133a050 NSObject
objc[29984]: [0x10480dc20] 0x10133a060 NSObject
objc[29984]: [0x10480dc28] 0x10133a070 NSObject
objc[29984]: [0x10480dc30] 0x10133a080 NSObject
objc[29984]: [0x10480dc38] 0x10133a090 NSObject
objc[29984]: [0x10480dc40] 0x10133a0a0 NSObject
objc[29984]: [0x10480dc48] 0x10133a0b0 NSObject
objc[29984]: [0x10480dc50] 0x10133a0c0 NSObject
objc[29984]: [0x10480dc58] 0x10133a0d0 NSObject
objc[29984]: [0x10480dc60] 0x10133a0e0 NSObject
objc[29984]: [0x10480dc68] 0x10133a0f0 NSObject
objc[29984]: [0x10480dc70] 0x10133a100 NSObject
objc[29984]: [0x10480dc78] 0x10133a110 NSObject
objc[29984]: [0x10480dc80] 0x10133a120 NSObject
objc[29984]: [0x10480dc88] 0x10133a130 NSObject
objc[29984]: [0x10480dc90] 0x10133a140 NSObject
objc[29984]: [0x10480dc98] 0x10133a150 NSObject
objc[29984]: [0x10480dca0] 0x10133a160 NSObject
objc[29984]: [0x10480dca8] 0x10133a170 NSObject
objc[29984]: [0x10480dcb0] 0x10133a180 NSObject
objc[29984]: [0x10480dcb8] 0x10133a190 NSObject
objc[29984]: [0x10480dcc0] 0x10133a1a0 NSObject
objc[29984]: [0x10480dcc8] 0x10133a1b0 NSObject
objc[29984]: [0x10480dcd0] 0x10133a1c0 NSObject
objc[29984]: [0x10480dcd8] 0x10133a1d0 NSObject
objc[29984]: [0x10480dce0] 0x10133a1e0 NSObject
objc[29984]: [0x10480dce8] 0x10133a1f0 NSObject
objc[29984]: [0x10480dcf0] 0x10133a200 NSObject
objc[29984]: [0x10480dcf8] 0x10133a210 NSObject
objc[29984]: [0x10480dd00] 0x10133a220 NSObject
objc[29984]: [0x10480dd08] 0x10133a230 NSObject
objc[29984]: [0x10480dd10] 0x10133a240 NSObject
objc[29984]: [0x10480dd18] 0x10133a250 NSObject
objc[29984]: [0x10480dd20] 0x10133a260 NSObject
objc[29984]: [0x10480dd28] 0x10133a270 NSObject
objc[29984]: [0x10480dd30] 0x10133a280 NSObject
objc[29984]: [0x10480dd38] 0x10133a290 NSObject
objc[29984]: [0x10480dd40] 0x10133a2a0 NSObject
objc[29984]: [0x10480dd48] 0x10133a2b0 NSObject
objc[29984]: [0x10480dd50] 0x10133a2c0 NSObject
objc[29984]: [0x10480dd58] 0x10133a2d0 NSObject
objc[29984]: [0x10480dd60] 0x10133a2e0 NSObject
objc[29984]: [0x10480dd68] 0x10133a2f0 NSObject
objc[29984]: [0x10480dd70] 0x101334f30 NSObject
objc[29984]: [0x10480dd78] 0x101334f40 NSObject
objc[29984]: [0x10480dd80] 0x101334f50 NSObject
objc[29984]: [0x10480dd88] 0x101334f60 NSObject
objc[29984]: [0x10480dd90] 0x101334f70 NSObject
objc[29984]: [0x10480dd98] 0x101334f80 NSObject
objc[29984]: [0x10480dda0] 0x101334f90 NSObject
objc[29984]: [0x10480dda8] 0x101334fa0 NSObject
objc[29984]: [0x10480ddb0] 0x101334fb0 NSObject
objc[29984]: [0x10480ddb8] 0x101334fc0 NSObject
objc[29984]: [0x10480ddc0] 0x101334fd0 NSObject
objc[29984]: [0x10480ddc8] 0x101334fe0 NSObject
objc[29984]: [0x10480ddd0] 0x101334ff0 NSObject
objc[29984]: [0x10480ddd8] 0x101335000 NSObject
objc[29984]: [0x10480dde0] 0x101335010 NSObject
objc[29984]: [0x10480dde8] 0x101335020 NSObject
objc[29984]: [0x10480ddf0] 0x101335030 NSObject
objc[29984]: [0x10480ddf8] 0x101335040 NSObject
objc[29984]: [0x10480de00] 0x101335050 NSObject
objc[29984]: [0x10480de08] 0x101335060 NSObject
objc[29984]: [0x10480de10] 0x101335070 NSObject
objc[29984]: [0x10480de18] 0x101335080 NSObject
objc[29984]: [0x10480de20] 0x101335090 NSObject
objc[29984]: [0x10480de28] 0x1013350a0 NSObject
objc[29984]: [0x10480de30] 0x1013350b0 NSObject
objc[29984]: [0x10480de38] 0x1013350c0 NSObject
objc[29984]: [0x10480de40] 0x1013350d0 NSObject
objc[29984]: [0x10480de48] 0x1013350e0 NSObject
objc[29984]: [0x10480de50] 0x1013350f0 NSObject
objc[29984]: [0x10480de58] 0x101335100 NSObject
objc[29984]: [0x10480de60] 0x101335110 NSObject
objc[29984]: [0x10480de68] 0x101335120 NSObject
objc[29984]: [0x10480de70] 0x101335130 NSObject
objc[29984]: [0x10480de78] 0x101335140 NSObject
objc[29984]: [0x10480de80] 0x101335150 NSObject
objc[29984]: [0x10480de88] 0x101335160 NSObject
objc[29984]: [0x10480de90] 0x101335170 NSObject
objc[29984]: [0x10480de98] 0x101335180 NSObject
objc[29984]: [0x10480dea0] 0x101335190 NSObject
objc[29984]: [0x10480dea8] 0x1013351a0 NSObject
objc[29984]: [0x10480deb0] 0x1013351b0 NSObject
objc[29984]: [0x10480deb8] 0x1013351c0 NSObject
objc[29984]: [0x10480dec0] 0x1013351d0 NSObject
objc[29984]: [0x10480dec8] 0x1013351e0 NSObject
objc[29984]: [0x10480ded0] 0x1013351f0 NSObject
objc[29984]: [0x10480ded8] 0x101335200 NSObject
objc[29984]: [0x10480dee0] 0x101335210 NSObject
objc[29984]: [0x10480dee8] 0x101335220 NSObject
objc[29984]: [0x10480def0] 0x101335230 NSObject
objc[29984]: [0x10480def8] 0x101335240 NSObject
objc[29984]: [0x10480df00] 0x101335250 NSObject
objc[29984]: [0x10480df08] 0x101335260 NSObject
objc[29984]: [0x10480df10] 0x101335270 NSObject
objc[29984]: [0x10480df18] 0x101335280 NSObject
objc[29984]: [0x10480df20] 0x101335290 NSObject
objc[29984]: [0x10480df28] 0x1013352a0 NSObject
objc[29984]: [0x10480df30] 0x1013352b0 NSObject
objc[29984]: [0x10480df38] 0x1013352c0 NSObject
objc[29984]: [0x10480df40] 0x1013352d0 NSObject
objc[29984]: [0x10480df48] 0x1013352e0 NSObject
objc[29984]: [0x10480df50] 0x1013352f0 NSObject
objc[29984]: [0x10480df58] 0x101335300 NSObject
objc[29984]: [0x10480df60] 0x101335310 NSObject
objc[29984]: [0x10480df68] 0x101335320 NSObject
objc[29984]: [0x10480df70] 0x101335330 NSObject
objc[29984]: [0x10480df78] 0x101335340 NSObject
objc[29984]: [0x10480df80] 0x101335350 NSObject
objc[29984]: [0x10480df88] 0x101335360 NSObject
objc[29984]: [0x10480df90] 0x101335370 NSObject
objc[29984]: [0x10480df98] 0x101335380 NSObject
objc[29984]: [0x10480dfa0] 0x101335390 NSObject
objc[29984]: [0x10480dfa8] 0x1013353a0 NSObject
objc[29984]: [0x10480dfb0] 0x1013353b0 NSObject
objc[29984]: [0x10480dfb8] 0x1013353c0 NSObject
objc[29984]: [0x10480dfc0] 0x1013353d0 NSObject
objc[29984]: [0x10480dfc8] 0x1013353e0 NSObject
objc[29984]: [0x10480dfd0] 0x1013353f0 NSObject
objc[29984]: [0x10480dfd8] 0x101335400 NSObject
objc[29984]: [0x10480dfe0] 0x101335410 NSObject
objc[29984]: [0x10480dfe8] 0x101335420 NSObject
objc[29984]: [0x10480dff0] 0x101335430 NSObject
objc[29984]: [0x10480dff8] 0x101335440 NSObject
objc[29984]: [0x104809000] ................ PAGE (hot)
objc[29984]: [0x104809038] 0x101335450 NSObject
我们看到这里有产生PAGE (hot) ,我们再以下两行打印
objc[29984]: [0x10480d000] ................ PAGE (full) (cold)
objc[29984]: [0x104809000] ................ PAGE (hot)
当前页满的时候,新建了一个PAGE,并设置hot
这里可能看出504刚好满一页,我们算下,页面的大小 是多少?
504 8 + 56=4088+8(哨兵对象)=4096=10244=4k。
通过这里可以看出PAGESIZE在MAC下是4k。
我们再看下AutoreleasePoolPage中的#define PAGE_MIN_SIZE (1 << PAGE_MIN_SHIFT),而#define PAGE_MIN_SHIFT 12,1左移12位,也就是2的12次方,就是4096。iOS是16k的在大小
在分页的时候哨兵对象并没有创建,因为我们已经有一个了,不需要再创建。
所以第二个对象就可以创建505个对象了。
那我们的pop是如何操作的,我们来看下objc_autoreleasePoolPop函数
void
objc_autoreleasePoolPop(void *ctxt)
{
AutoreleasePoolPage::pop(ctxt);
}
我们再看一这里的pop函数
static inline void
pop(void *token)
{
AutoreleasePoolPage *page;
id *stop;
if (token == (void*)EMPTY_POOL_PLACEHOLDER) {
// Popping the top-level placeholder pool.
page = hotPage();
if (!page) {
// Pool was never used. Clear the placeholder.
return setHotPage(nil);
}
// Pool was used. Pop its contents normally.
// Pool pages remain allocated for re-use as usual.
page = coldPage();
token = page->begin();
} else {
page = pageForPointer(token);
}
stop = (id *)token;
if (*stop != POOL_BOUNDARY) {
if (stop == page->begin() && !page->parent) {
// Start of coldest page may correctly not be POOL_BOUNDARY:
// 1. top-level pool is popped, leaving the cold page in place
// 2. an object is autoreleased with no pool
} else {
// Error. For bincompat purposes this is not
// fatal in executables built with old SDKs.
return badPop(token);
}
}
if (slowpath(PrintPoolHiwat || DebugPoolAllocation || DebugMissingPools)) {
return popPageDebug(token, page, stop);
}
return popPage<false>(token, page, stop);
}
这里获取到page = hotPage();这个hot页,如果不是hot。
if (!page) {
// Pool was never used. Clear the placeholder.
return setHotPage(nil);
}
置空
page = coldPage();
token = page->begin();
不断的移动这个页面,移除popPage<false>(token, page, stop);这里的调用
template<bool allowDebug>
static void
popPage(void *token, AutoreleasePoolPage *page, id *stop)
{
if (allowDebug && PrintPoolHiwat) printHiwat();
page->releaseUntil(stop);
// memory: delete empty children
if (allowDebug && DebugPoolAllocation && page->empty()) {
// special case: delete everything during page-per-pool debugging
AutoreleasePoolPage *parent = page->parent;
page->kill();
setHotPage(parent);
} else if (allowDebug && DebugMissingPools && page->empty() && !page->parent) {
// special case: delete everything for pop(top)
// when debugging missing autorelease pools
page->kill();
setHotPage(nil);
} else if (page->child) {
// hysteresis: keep one empty child if page is more than half full
if (page->lessThanHalfFull()) {
page->child->kill();
}
else if (page->child->child) {
page->child->child->kill();
}
}
}
这里先
AutoreleasePoolPage *parent = page->parent;
拿到parent页面,接着
page->kill();
杀掉当前页,然后
setHotPage(parent);
把父页设置成hot。
而kill就是不断的内存平移
void kill()
{
// Not recursive: we don't want to blow out the stack
// if a thread accumulates a stupendous amount of garbage
AutoreleasePoolPage *page = this;
while (page->child) page = page->child;
AutoreleasePoolPage *deathptr;
do {
deathptr = page;
page = page->parent;
if (page) {
page->unprotect();
page->child = nil;
page->protect();
}
delete deathptr;
} while (deathptr != this);
}
先入后出,不断的递归。
通过哨兵对象是否等于哨兵边界来判断标记完成了。
5 自动释放池的拓展
- 临时变量什么时候释放
- 自动释放池原理
- 自动释放池能否嵌套使用
临时变量什么时候释放就是在作用域的范围
自动释放池原理就是上述所讲
自动释放池可以嵌套使用
我们看下代码
#import <Foundation/Foundation.h>
extern void _objc_autoreleasePoolPrint(void);
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *objc = [[[NSObject alloc] init] autorelease];
@autoreleasepool {
NSObject *objc2 = [[[NSObject alloc] init] autorelease];
NSLog(@"%@", objc2);
_objc_autoreleasePoolPrint();
}
_objc_autoreleasePoolPrint();
}
return 0;
}
我们运行下项目,看下效果,如下
objc[30334]: ##############
objc[30334]: AUTORELEASE POOLS for thread 0x1000ebe00
objc[30334]: 4 releases pending.
objc[30334]: [0x100811000] ................ PAGE (hot) (cold)
objc[30334]: [0x100811038] ################ POOL 0x100811038
objc[30334]: [0x100811040] 0x10060d9b0 NSObject
objc[30334]: [0x100811048] ################ POOL 0x100811048
objc[30334]: [0x100811050] 0x10060cdd0 NSObject
objc[30334]: ##############
objc[30334]: ##############
objc[30334]: AUTORELEASE POOLS for thread 0x1000ebe00
objc[30334]: 2 releases pending.
objc[30334]: [0x100811000] ................ PAGE (hot) (cold)
objc[30334]: [0x100811038] ################ POOL 0x100811038
objc[30334]: [0x100811040] 0x10060d9b0 NSObject
objc[30334]: ##############
KCObjcBuild was compiled with optimization - stepping may behave oddly; variables may not be available.
从这可以看出objc2是加入到objc2的自动释放池中,这里也说明是可以嵌套使用,相互不影响。
但是如果不autorelease是不加入到自动释放池中的(在MAC中)
但是以alloc、new、copy、mutablecopy创建的是不会加入到自动释放池中的
总结
这篇文章主要介绍了自动释放池的结构、创建、压栈等相关知识, 到这里内存管理的相关知识,我们已经基本介绍完了,但这只是个人的一份见解,内存相关的知识还有很多很多,本人也只是对其有那么一点点的研究,如有遗漏,还望海涵。