OC 内存泄露 自动释放池
花絮:看到下面的代码就想起这么一个调侃:
一个老程序员,功成名就,金盆洗手不在写代码后,决定练练书法。提笔思索良久后在纸上写下:Hello world!
/*********************************************************************************/
1 首先说下自动释放池的底层实现
它是通过以 AutoreleasePoolPage 为结点的双向链表来实现的。很类似栈的方式:对应push操作(底层是标记一个哨兵),这时相当于创建了一个自动释放池。当一个对象收到发送autorelease消息时,它被添加刚创建的自动释放池中,当自动释放池被回收时(对应pop操作),哨兵之后添加进来的对象从池中被删除, 并且会给它们发送release消息。则对象引用计数-1,如果为0则释放内存。很明显ARC相对于MRC,对象会延迟释放。
2 举例
有这么一段代码:largeNumber可以当做一个很大的数
for (int i = ; i < largeNumber; i++) {
NSString *myStr = @"Hello world"; // 原谅我用Hello world
myStr = [myStr stringByAppendingString:[NSString stringWithFormat:@"-%05d-",i]];
}
那么会有什么问题呢?
如果largeNumber不大时没有问题,但是当它很大时问题非常严重!造成内存峰值。虽然ARC会自动释放内存,但是只有pop操作(完成一次runloop消息循环或@autoreleasepool {}结尾时)才会给池子里面的所有对象做一次release操作。
当我们使用for循环创建很多个使用autorelease方式创建的NSString对象的时候,将所有的对象的释放权都交给了这个释放池,而这个释放池会等待完整的循环之后才有可能释放,因此就会使对象无法及时释放,堆积在内存造成内存峰值。
代码应该这样修改:在循环内添加一个自动释放池,此时自动释放池就会处于当前线程的栈顶,那么每执行一次循环,就会新建一个自动释放池(push),循环结束进行一次(pop操作),那么添加在池子里面的对象就会被释放,则不会造成内存峰值。
for (int i = ; i < largeNumber; i++) {
@autoreleasepool {
NSString *myStr = @"Hello world";
myStr = [myStr stringByAppendingString:[NSString stringWithFormat:@"-%05d-",i]];
}
}
最新文章
- 跟着百度学PHP[6]超级全局变量
- nfs文件系统挂载错误及解决方法
- jsp js action之间的传值
- 未能正确加载 ”Microsoft.VisualStudio.Editor.Implementation.EditorPackate“包错误解决方法
- [codevs2070]爱情之路
- 关于学习netty的两个完整服务器客户端范例
- 宣布 Azure Backup 支持备份 Windows Server 2008
- 图解三种APP的区别
- Swap Nodes in Pairs——LeetCode
- C语言初学 数组 打印菱形
- php php打乱数组二维数组、多维数组
- 【Java】【Fulme】Flume-NG源代码阅读之SpoolDirectorySource
- iOS开发者的管理工具-CocoaPods安装
- fiddler基本功能介绍
- Golang知识图谱
- HDU5543(SummerTrainingDay03-O DP)
- element-ui table中排序 取消表格默认排序问题
- Html的本质及在web中的作用
- jq 分页
- Object-c和Java中的代理
热门文章
- 这些HTML、CSS知识点,面试和平时开发都需要 No10-No11
- C#中方法的声明
- Ubuntu14.04安装postgresql9.4
- 使用 TOP 限制更新的数据
- 在_Layout模版中使用@Styles.Render()没有效果
- 【C#】VS2015开发环境的安装和配置(二)2016-08-03更新
- mysql,命令导入\导出表结构或数据
- volcanol_Linux_ 问题汇总系列_4_Thinkpad_E40_0578MDC_在Fedora 13 Linux(FC13)中如何安装无线网卡驱动
- Thinkphp各种方法知识图谱
- 在selenium2.0中使用selenium1.0的API