ios内存管理
来源:互联网 发布:河南网络广播电视台 编辑:程序博客网 时间:2024/06/09 13:43
1.堆和栈的区别
管理方式:
对于栈来讲,是由编译器自动管理,无需我们手工控制;
对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统 预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示 overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地 址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:
对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。
对于栈来讲,则不会存在这个 问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:
堆都是动态分配的,没有静态分配的堆。
栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由 alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的 效率比较高。
堆则是C/C++函数库提供的,它的机制是很复杂的。
2.内存管理原则是什么?
1. 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
例如,你在一个函数中alloc生成了一个对象,且这个对象只在这个函数中被使用,那么你必须在这个函数中调用release或autorelease。如果你在一个class的某个方法中alloc一个成员对象,且没有调用autorelease,那么你需要在这个类的dealloc方法中调用release;如果调用了autorelease,那么在dealloc方法中什么都不需要做。
2. 除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。
3. 谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。有时候你的代码中明明没有retain,可是系统会在默认实现中加入retain。
3.谈一谈自动释放池
自动释放池(Autorelease pool)是OC的一种内存自动回收机制,可以将一些临时变量通过自动释放池来回收统一释放.自动释放池本事销毁的时候,池子里面所有的对象都会做一次release操作.
自动释放池并不包含实际的对象本身,仅仅是对池释放的时候要释放的对象的引用,通过像当前的自动释放池发送一条autorelease消息,就可以将一个对象添加到其中,以便以后释放。
Cocoa应用程序中的每个线程都会维护一个自己的NSAutoreleasePool对象的堆栈。当一个线程终止时,它会自动地释放所有与自身相关的自动释放池。在基于Application Kit的应用程序中,自动释放池会在程序的主线程中被自动创建和销毁,所以,您的代码通常无需处理它们。但是,如果您在Application Kit的主线程之外发起Cocoa调用,则您需要创建自己的自动释放池。如果您正在编写一个Foundation应用程序,或者如果您拆分了一个线程,则是属于这种情况。
4.什么是强指针,什么是弱指针?
强指针在当进行对象地址的赋值操作时会保留新值并释放旧值,当其退出指针作用域时释放。而弱指针则类似于手动内存管理时的指针,它仅仅是一个指针而已,不做额外的保留和释放,在对象被回收时会自动置为nil。在程序中使用__strong关键字指定强指针,使用__weak关键字指定弱指针,默认为强指针。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
if语句块的第一行代码创建了一个数组,其中包含三个字符串对象,然后将其地址赋值给stringArray。第二行将数组的首元素地址赋值给firstObj,即指向字符串@”A”。第三行将数组首元素移出数组。第四行打印firstObj的描述信息。最后退出if语句块。
在未开启ARC时,由于元素在被移出数组时会被数组释放,所以在调用NSLog函数时@”A”已经被回收,firstObj指向的是一个无效的地址(野指针、僵尸),这会导致程序崩溃。
而当开启了ARC时,上述代码就是正确的。当执行到第二行时,stringArray和firstObj均为强指针(默认为强指针),分别保留数组和@”A”,此时@”A”的所有者为数组和firstObj。到第三行,@”A”的所有者为firstObj,未被回收,所以NSLog语句没有问题。最后退出if语句块时,stringArray和firstObj退出作用域,分别释放并回收数组和@”A”。
当然,你可以在定义stringArray和firstObj时指定__strong关键字:
- 1
- 2
- 3
- 1
- 2
- 3
不过由于默认为强指针,所以__strong关键字是可以忽略的。
由于强指针会一直保留着对象,所以当你确实需要将其释放时,需要手动将强指针赋值为nil,否则对象一直不会被回收,会导致系统内存资源不足。
再来说说弱指针。请看如下代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
由于firstObj为弱指针,前两个NSLog输出为A,而最后一个则为(null)。这说明当对象被回收时,所有指向该对象的弱指针均会被置为nil,但这需要时间。
读到这里,你应该知道下面的代码有什么问题了吧:
- 1
- 2
- 3
- 1
- 2
- 3
当启用了ARC之后,(基本上)不会出现内存泄漏、使用野指针、访问僵尸对象的情况 。
5.多次调用对象的autorelease方法会导致什么问题?
多次将地址存到自动释放池中,导致野指针异常
- IOS 内存管理
- iOS内存 管理 一点
- ios内存管理
- IOS内存管理小结
- iOS内存管理
- 再论iOS内存管理
- iOS内存管理
- IOS 内存管理
- IOS内存管理
- IOS内存管理
- iOS内存管理
- ios 内存管理基础知识
- ios内存管理
- iOS 内存管理
- IOS内存管理详解
- iOS 内存管理总结
- ios内存管理
- ios 内存管理
- Android Toast 设置statusbar沉浸式后 文字偏移问题
- SERVLET中的doGet与doPost两个方法之间的区别
- C#发起带证书的http请求(通常用于微信发红包)
- Oracle递归查询
- 获取鼠标的X,Y的位置
- ios内存管理
- bug宝典JAVA篇 java.util.zip.ZipException: invalid LOC header (bad signature)
- npm 安装 angular-cli 创建项目
- 大数据平台的技术演化之路 诸葛io平台设计实例
- 仿ios动态鱼等壁纸的方法处理
- Entity Framework 5.0 访问MySql不安装mysql-connector-net-6.9.6的实践
- js中undefined,null,NaN的区别
- java中的面向对象
- 数组---在数组中查找元素