内存管理

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];
}

@end
int 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方法种释放该对象。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值