内存管理

来源:互联网 发布:网络视觉营销 编辑:程序博客网 时间:2024/05/22 12:25

1.内存区域

内存分为5个区:堆,栈,自由存储区,全局/静态存储区 和 常量存储区。

栈(stack):编译器需要时分配,不需要时自动清除的变量存储区。常是局部变量、函数参数等。

堆(heap):由new分配的内存块,编译器不负责释放,由应用程序去控制。一般一个new对应一个delete。若程序没有释放,在程序结束后,os自动回收。

例子:

void f()

{

int *p = new int [5];

}

思考:

那部分是堆,那部分是栈?

如何释放该块内存?是delete p 吗?


p是栈,int[5]是堆

p自动释放,int[5]是delete p。


内存管理是一个不易解决的问题。

需要时分配内存

在程序运行结束时释放内存

不要使用任何已经释放的内存


如何解决垂悬指针??

free(pint)

pint = NULL;

释放之后,置空


oc的内存管理使用引用计数,和半自动释放机制。


对象生命周期

包括:

诞生(通过alloc)

生存(接收消息和执行操作)

交友(借助方法的组合和参数)

释放(生命结束)

引用计数

又称保留计数,标示对象当前被引用的次数,标志对象使用寿命是否结束。

当前对象引用计数为0时,才能释放该对象占用的内存。

对象创建时,引用计数自动设置为1.


1.每个对象都又一个引用计数器(对栈)

代码访问一个对象时,将对象的保留计数器值加1.

访问结束保留计数器值减1

保留计数器值为0时,对象被销毁,其占用的内存将被系统收回。

2.利用alloc、new、或copy消息创建对象时:(对堆)

将对象的保留计数器置为1

发送retain消息,对象保留计数器加1;

发送release消息,对象保留计数器值减1;

发送retain count 消息时,获得保留计数器当前值。

保留计数器值为0时,系统自动发送一条dealloc消息,用户可重写该消息,但不可直接调用。

保留计数器常用方法:

-(id)retain;

-(void)release;

-(unsigned)retainCount;

使用实例:

[[car retain] setTire : tireAtIndex:2];

要求car对象保留计数器值加1并执行setTire操作


#import <Foundation/Foundation.h>@interface RetainTracker : NSObject {}@end@implementation RetainTracker-(id)init{    if(self = [super init])    {}    return self;}-(void)dealloc{    [super dealloc];}@endint main (int argc, const char * argv[]){    RetainTracker *tracker = [RetainTracker new];        NSLog(@"%lu",[tracker retainCount]);//1        [tracker retain];    NSLog(@"%lu",[tracker retainCount]);//2        [tracker retain];    NSLog(@"%lu",[tracker retainCount]);//3        [tracker release];    NSLog(@"%lu",[tracker retainCount]);//2       [tracker retain];    NSLog(@"%lu",[tracker retainCount]);//3        [tracker release];    NSLog(@"%lu",[tracker retainCount]);//2        [tracker release];    NSLog(@"%lu",[tracker retainCount]);//1        [tracker release];    NSLog(@"%lu",[tracker retainCount]);//1        return 0;}


对象所有权

一个对象拥有指向其他对象的实例变量,则称该对象拥有这些对象。复合
一个函数创建了一个对象,则称该函数拥有该对象。函数内部向一个类发送消息
多个实体拥有某个对象的所有权,清理过程比较复杂
谁拥有对象,谁负责清理


   Engine *engine = [Engine new];    Car *car1 = [Car new];    Car *car2 = [Car new];        [car1 setEngine:engine];    [engine release];    [car2 setEngine:engine];


内存管理原则:

当一个对象的某个所有者需要使用它时,保证这个对象存在。

当一个对象的所有所有者都不再需要它时,保证这个对象被销毁。

只要任何一个所有者在使用完一个对象之后释放掉它,那么以上内存管理的目标就可以实现。

所有者应遵守:

拥有一个对象》使用一个对象》放弃对象的所有权

引用计数应遵守:

还需要这个对象时,保持对其增减为正。

不再需要这个对象时,保持对其增减为0。


自动释放池:

存放实体的池,这些实体是对象,能被自动释放。

给一个对象发送autorelease 消息时,实际上就是将该对象添加到nsautoreleasepool种。

当自动释放池被销毁时,会向该池种的所有对象发送release消息。


当使用new,alloc,或copy方法获得一个对象时,则需要在拥有该对象的对象的存方法种保留该对象。在拥有该对象的对象的dealloc方法种释放该对象。

当使用方法获得一个对象时,则需要在拥有该对象的对象的存方法种保留该对象。在拥有该对象的对象的dealloc方法种释放该对象。