ios 内存简单介绍

来源:互联网 发布:jave编程app 编辑:程序博客网 时间:2024/05/16 15:28

以前一直就是简单的去看看别人的帖子  学习内存   但是真心是不懂  不懂   相信更多的人和我一样   对于内存是迷迷糊糊,学过又好像是没有学过。

估计这种贱人的回答  只有我能说出来   哈哈 

这几天不太忙  我就打算争取把内存这块全部吃透了  争取多上例子  让大家能看到实例说明   毕竟我这样的小白还是存在的 

不希望能多透彻  就希望能简简单单的帮助一些人好好学习一下内存    

------------------------------------------------------------------------------------------------------------------------------------------

 Person *p=[[Person alloc]init];    p.name=@"Kenshin";    p.age=28;        NSLog(@"retainCount=%lu",[p retainCount]);    //结果:retainCount=1        [p retain];//引用计数器+1    NSLog(@"retainCount=%lu",[p retainCount]);    //结果:retainCount=2        [p release];//调用1次release引用计数器-1    NSLog(@"retainCount=%lu",[p retainCount]);    //结果:retainCount=1    [p release];    //结果:Invoke Person's dealloc method.    p=nil;

咱们用简单的例子  来说明一点 最简单的问题哈 

其实在ObjC中内存的管理是依赖对象引用计数器来进行的:在ObjC中每个对象内部都有一个与之对应的整数(retainCount),叫“引用计数器”,当一个对象在创建之后它的引用计数器为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1(ObjC中调用一个对象的方法就是给这个对象发送一个消息),当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。

其实上面说的最明白就是  只要allco  retain  new  copy   引用计数器就会增加1     

涉及到 release  就会-1  当retainCount为0的时候  就会自动调用dealloc来注销了


1.

@property(nonatomic,retain)NSArray *arr;

@synthesize arr;

self.arr = [[NSArry alloc] init];

这个计数器应该是多少呢 ?

引用计数器为2   对的  因为这个做了一个 retain   

2.

/*

*取得非自己生成并持有的对象

*/

id obj = [NSMutableArray array];

/*

 *自己持有对象

 */

[obj retain];

补充一下:

很多人都会问  为什么copy   mutablecopy也能引用计时器加1呢   下面我来给大家做一个简单的介绍哈 

copy是利用基于NSCopying方法约定的,由copyWithZone:生成并持有对象的副本    也就是说 他变相的实现了retain  所以引用计数器+1


其实   由于ios源码封装  下面 将展示一个比较重要的事情  就是展示出封装的源码 (正确与否,其实我也不太了解  只是从书本上拿下了  大家分享一下)

alloc实现方法

+(id)alloc{return [self allocWithZone: NSDefaultMallocZone()];}+(id)allocWithZone:(NSZone *)z{return NSAllocateObject(self, 0, z);}
通过allocWithZone:类方法调用NSAllocateObject函数分配了对象。 简单介绍NSAllocateObject函数

struct obj_layout{NSUInteger retained;};inline idNSAllocateObject(Class aClass, NSUinteger extraBytes, NSZone *zone){int size = 计算容纳对象所需内存大小;id new = NSZoneMalloc(zone,size);memset(new,0,size);new = (id)&((struct obj_layout *)new) [1];}

NSAllocateObject 函数通过调用NSZoneMalloc函数来分配存放对象所需的内存空间,之后将该内存空间置0,最后返回作为对象而使用的指针。

总结:调用alloc时--->allocWithZone--->NSAllocateObject--->实现的内存空间


retainCount实现方法

id obj = [[NSObject alloc] init];NSLog(@“retainCount = %d”,[obj retainCount]);/* *显示结果retainCount = 1 */继续看一下GNUstep源码实现过程-(NSUInteger)retainCount{return NSExtraRefCount(self) +1;}inline NSUIntegerNSExtraRefCount(id anObject){return ((struct obj_layout *) anObject) [-1].retained;}


retain实现方法

[obj retain];如何实现的呢?  学习GNUstep来看一下哈-(id)retain{NSIncrementExtraRefCount(self);return self;}inline voidNSInctementExtraRefCount(id anObject){if(((struct obj_layout *)anObject) [-1].retained == UINT_MAX -1)[NSException raise:NSInternalInconsistencyExceptionformat:@“NSIncrementEXtraRefCount() asked to increment too far”];((struct obj_layout *) anObject) [-1].retained++;}虽然写入了当retained变量超出最大值时发生异常的代码,但实际上只运行了使retained变量加1的retained++代码。


release实现方法

同样的release实例方法进行retained—并在该引用计数变量为0时做出处理.

[obj release];具体实现   看一下哈!-(void)release{if(NSDecrementExtraRefCountWasZero(self))[self dealloc];}BOOLNSDecrementExtraRefCountWasZero(id anObject){if(((struct obj_layout *)anObject) [-1],retained == 0){return YES;}else{((struct obj_layout *)anObject) [-1].retained—-;return NO;}}应该算是和当时想的一致    当retained变量大于0时,进行-1;当retained等于0时,调用dealloc实例方法


dealloc实现方法

-(void) dealloc{NSDeallocateObje(self);}inline voidNSDeallocateObject (id anObject){struct obj_layout *o = &((strcut obj_layout *)anObjcet) [-1];free(0);}不多介绍了  看看明白原理即可

内存释放的原则

手动管理内存有时候并不容易,因为对象的引用有时候是错综复杂的,对象之间可能互相交叉引用,此时需要遵循一个法则:谁创建,谁释放

先简单介绍到这里吧!   虽然不太清楚 以后慢慢补充吧   

上面的讲解希望能给我和你一点点的感触!  不求太多 一点点即可哈 


0 0
原创粉丝点击