自动释放池什么时候创建,什么时候销毁?
2015-09-01 10:34
253 查看
自动释放池什么时候创建,什么时候销毁?
运行循环结束前会释放自动释放池,还有就是池子满了,也会销毁。
面试题
下面代码存在内存问题么?如果存在如何解决?为什么
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
int lagerNum = 1024 * 1024 * 2 ;
for(int i = 0 ; i < lagerNum; i++)
{
NSString *str = [NSString stringWithFormat:@"Hello"];
str = [str uppercaseString];
str = [NSString stringByAppendingFormat:@"-%@",@"World!"];
}
}
解题思路:首先根据类方法创建的,而且他们都用的是类方法,类方法是每次调用,每次都会为你创建一个新的对象。还有就是通过对象方法创建的对象,如果不是通过alloc new retain copy 创建的对象,那么他们内部都有一个autorelease.(可以通过NSLog(@"%p",str),查看每次调用过后的内存地址,他们的内存地址是不一样的),他们都是通过自动释放池进行自动释放的,所以这些字符串对象会等到循环结束时才会进行释放,而此时它们会消耗大量的内存资源,所以她们存在内存问题。---通过xcode查看内存峰值就可以看出运行时的变化
解决办法:从题中看出每次循环这个对象就不会再调用了,所以,我们可以将每一次循环放入到自动释放池中去,这样每次循环结束后变会将此次创建的对象销毁,如下代码
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
int lagerNum = 1024 * 1024 * 2 ;
for(int i = 0 ; i < lagerNum; i++)
{
@autoreleasepool{
NSString *str = [NSString stringWithFormat:@"Hello"];
str = [str uppercaseString];
str = [NSString stringByAppendingFormat:@"-%@",@"World!"];
}
}
}
------考虑到lagerNum这个数据足够大,所以我们在内部创建自动释放池,如果lagerNum不足够大,那么我们可以在for循环外面创建自动释放池。
默认主线的运行循环(runloop)是开启的,子线程的运行循环(runloop)默认是不开启的,也就意味着子线程中不会创建autoreleasepool,所以需要我们自己在子线程中创建一个自动释放池。(子线程里面使用的类方法都是autorelease,就会没有池子可释放,也就意味着后面没有办法进行释放,造成内存泄漏。)----在主线程中如果产生事件那么runloop才回去创建autoreleasepool,通过这个道理我们就知道为什么子线程中不会创建自动释放池了,因为子线程的runloop默认是关闭的,所以他不会自动创建autoreleasepool,需要我们手动添加。
运行循环结束前会释放自动释放池,还有就是池子满了,也会销毁。
面试题
下面代码存在内存问题么?如果存在如何解决?为什么
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
int lagerNum = 1024 * 1024 * 2 ;
for(int i = 0 ; i < lagerNum; i++)
{
NSString *str = [NSString stringWithFormat:@"Hello"];
str = [str uppercaseString];
str = [NSString stringByAppendingFormat:@"-%@",@"World!"];
}
}
解题思路:首先根据类方法创建的,而且他们都用的是类方法,类方法是每次调用,每次都会为你创建一个新的对象。还有就是通过对象方法创建的对象,如果不是通过alloc new retain copy 创建的对象,那么他们内部都有一个autorelease.(可以通过NSLog(@"%p",str),查看每次调用过后的内存地址,他们的内存地址是不一样的),他们都是通过自动释放池进行自动释放的,所以这些字符串对象会等到循环结束时才会进行释放,而此时它们会消耗大量的内存资源,所以她们存在内存问题。---通过xcode查看内存峰值就可以看出运行时的变化
解决办法:从题中看出每次循环这个对象就不会再调用了,所以,我们可以将每一次循环放入到自动释放池中去,这样每次循环结束后变会将此次创建的对象销毁,如下代码
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
int lagerNum = 1024 * 1024 * 2 ;
for(int i = 0 ; i < lagerNum; i++)
{
@autoreleasepool{
NSString *str = [NSString stringWithFormat:@"Hello"];
str = [str uppercaseString];
str = [NSString stringByAppendingFormat:@"-%@",@"World!"];
}
}
}
------考虑到lagerNum这个数据足够大,所以我们在内部创建自动释放池,如果lagerNum不足够大,那么我们可以在for循环外面创建自动释放池。
默认主线的运行循环(runloop)是开启的,子线程的运行循环(runloop)默认是不开启的,也就意味着子线程中不会创建autoreleasepool,所以需要我们自己在子线程中创建一个自动释放池。(子线程里面使用的类方法都是autorelease,就会没有池子可释放,也就意味着后面没有办法进行释放,造成内存泄漏。)----在主线程中如果产生事件那么runloop才回去创建autoreleasepool,通过这个道理我们就知道为什么子线程中不会创建自动释放池了,因为子线程的runloop默认是关闭的,所以他不会自动创建autoreleasepool,需要我们手动添加。
相关文章推荐
- js,php 使用正则表达式解析GPS数据
- 项目:××官网改版总结经验和收获
- mysql常用语句
- 8月国内网站流量统计TOP5:360安全中心季军
- android调整版本问题记载
- RevitAPI: PlanarFace.Normal 和 PlanarFace.FaceNormal
- voltDB 查询语句解析过程 初步分析
- SQL Server 查询数据库中所有的表名及行数
- 关于C++中的显示调用explicit
- Python Unitest 源码阅读:概述
- 常规功能和模块自定义系统(cfcmms)—005开发环境搭建和创建项目
- JNI编程指南-第四章 字段和方法
- SQL配置文件实例 Sql_Map.xml
- OptionMenu和ContextMenu使用介绍
- Android Studio 写打印Log的代码出错
- 专利权发明的两大特性
- 设计模式系列3--适配器模式
- nyoj 525 一道水题【字符串(分割)】
- Oracle 051 的几个题 (oracle 11g)
- FilenameFilter总结