Ojbect C中内存管理漫谈.

来源:互联网 发布:淘宝商城香奈儿包包 编辑:程序博客网 时间:2024/05/16 19:47

      

     在java中内存管理机制最基本最原始的是引用计数的方式来管理内存,堆内存中一个对象的引用为空时,那么这个对象在虚拟机垃圾回收时最容易被回收掉。java中的引用是有向线段来表示。当有循环引用的时候我们采用弱引用的方式来相互引用,这样系统会根据自己的需要来回收掉其中的对象内存。其实Object C的内存和这个基本类似。             

             在object-c中,系统自动会为每个创建的对象保存一个引用计数器。当对象被创建时,引用计数设置为1,每一次必须保持该对象时,需要发送(即调用)retain来使得引用计数加1。不再需要对象时,可以发送release消息,使得引用计数减1。当引用计数为0的时候,系统就会释放它的内存(通过向对象发送dealloc消息,也就是真正地去回收对象的内存)。另外,可以用retainCount来得到这个对象的引用计数,返回的类型是NSUInteger整数。基本的调用方式如下:

[obj retain];

[obj release];

[obj retainCount]; 

1、下面通过一个例子来理解retain,release以及retainCount,从而来理解Object C的内存

//1. ClassTest1.h#import <Foundation/NSObject.h>@interface ClassTest1: NSObject @end

//2. ClassTest1.m#import "ClassTest1.h"@implementation ClassTest1//在.h中有声明,不必声明dealloc方法-(void) dealloc {    printf( "Deallocing ClassTest1\n" );    [super dealloc];}@end

//3. main.m#import <stdio.h>#import "ClassTest1.h"int main( int argc, const char *argv[] ) {    printf("test case 1:\n");    ClassTest1 *obj1 = [[ClassTest1 alloc] init];    ClassTest1 *obj2 = [[ClassTest1 alloc] init];    printf( "obj1 retain count: %i\n", [obj1 retainCount] );    printf( "obj2 retain count: %i\n", [obj2 retainCount] );    printf("test case 2:\n");    [obj1 retain]; // 2    [obj1 retain]; // 3    [obj2 retain]; // 2    printf( "obj1 retain count: %i\n", [obj1 retainCount] );    printf( "obj2 retain count: %i\n", [obj2 retainCount] );        printf("test case 3:\n");    [obj1 release]; // 2    [obj2 release]; // 1    printf( "obj1 retain count: %i\n", [obj1 retainCount] );    printf( "obj2 retain count: %i\n", [obj2 retainCount] );        // release    [obj1 release]; // 1  //这里要注意,有几个retain,就要有几个release.    [obj1 release]; // 0  //而且,只调用一次delloc    [obj2 release]; // 0    return 0;}
执行后的结果:

test case 1:obj1 retain count: 1obj2 retain count: 1test case 2:obj1 retain count: 3obj2 retain count: 2test case 3:obj1 retain count: 2obj2 retain count: 1Deallocing ClassTest1Deallocing ClassTest1

说明:

  (1).retain了多少次,就要release多少次, 而且delloc方法只会被调用一次; 
  (2). 一个原则是,是你自己申请的内存,就得由你来负责释放它;而不是你申请的,请不要随意去释放它,这不是你的责任; 
  (3). 每次retain对象时,应该release或autoreleas它。 
在老版本的IOS中对象的retainCount必须为0的时候这个对象才能被释放掉。

2、强引用和弱引用

     默认情况下,一个指针都会使用 __strong 属性,表明这是一个强引用。这意味着,只要引用存在,对象就不能被销毁。这是一种所期望的行为:当所有(强)引用都去除时,对象才能被收集和释放。不过, 有时我们却希望禁用这种行为:一些集合类不应该增加其元素的引用,因为这会引起对象无法释放。在这种情况下,我们需要使用弱引用(不用担心,内置的集合类 就是这么干的),使用 __weak 关键字。NSHashTable 就是一个例子。当被引用的对象消失时,弱引用会自动设置为 nil。
1.(weak与strong)不同的是:当一个对象不再有strong类型的指针指向它的时候,它就会被释放,即使改对象还有_weak类型的指针指向它;
2.一旦最后一个指向该对象的strong类型的指针离开,这个对象将被释放,如果这个时候还有weak指针指向该对象,则会清除掉所有剩余的weak指针
       所以当我们有循环引用的时候,这时候用弱引用会避免内存泄漏


3. 自动回收原理简介

要使用自动回收我们必须手工创建自动释放对象池,NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。当NSAutoreleasePool自身释放的时候,会遍历数组中的所有对象,并且调用release方法。如果对象的retainCount=0 那么系统会释放这些对象,如果retainCount>0,则会内存泄露。
在某些情况下,NSAutoreleasePool 调用的销毁方法比较迟,这个时候会占用大量的内存,我们也可以使用内嵌的方式,创建多个NSAutorelease的实例,让占用的资源立马释放掉。
0 0
原创粉丝点击