mikixiyou 发表于 2013-1-30 20:27:35

iOS中引用计数内存管理机制分析



   在iOS中引用计数是内存的管理方式,虽然在iOS5版本中,已经支持了自动引用计数管理模式,但理解它的运行方式有助于我们了解程序的运行原理,有助于debug程序。
   操作系统的内存管理分成堆和栈。


   在堆中分配的内存,都试用引用计数模式;在栈中则不是。


   NSString定义的对象是保存在栈中,所以它没有引用计算。看一些书上说它的引用计算会是fffffffff最大整数,测试的结果显示它是-1.对该对象进行retain操作,不好改变它的retainCount值。


   MutableNSString定义的对象,需要先分配堆中的内存空间,再初始化才能使用。它是采用引用计数管理内存的。对该对象做retainCount操作则每次增加一个。


   其实,引用计数是对内存区域的空间管理方式,是应从内存块的视角去看的。任何对象都是指向它的指针,有多少个指针指向它,就有多少个引用计算。
   如果没有任何指针指向该内存块了,很明显,该内存块就没有对象引用了,引用计算就是0,系统会人为该内存区域已经空闲,于是立即清理,也就是更新一下管理堆的链表中某个标示位。




(miki西游 @mikixiyou 原文链接: http://mikixiyou.iteye.com/blog/1592958)


     测试方法如下:


     在xcode中建立一个非arc的项目,单视图即可。建立一个按钮的操作方法。


     - (IBAction)testRC:(id)sender {


     NSInteger i;
     i=self.i_test;


     if((i%2)==1)
     {
     NSString * str1=@"welcome";
     NSString * str2=@"mlgb";
     NSString * str3;
     NSString * str4=@"welcome";
     NSLog(@"str1 addr is %p",str1);
     NSLog(@"str2 addr is %p",str3);
     NSLog(@"str3 addr is %p",str3);
     NSLog(@"str4 addr is %p",str4);


     NSLog(@"str1 retainCount is %i",);
     NSLog(@"str2 retainCount is %i",);
     //NSLog(@"str3 retainCount is %i",); 该使用会导致crash,因为str3没有指向任何内存区域。




     str3=;
     NSLog(@"str3=;");
     NSLog(@"str1 retainCount is %i",);
     NSLog(@"str3 retainCount is %i",);
     str3=;
     NSLog(@"str3=;");
     NSLog(@"str2 retainCount is %i",);
     NSLog(@"str3 retainCount is %i",);


     /*
     结果如下:
     2012-07-14 11:07:38.358 testMem str1 addr is 0x3540
     2012-07-14 11:07:38.360 testMem str2 addr is 0x0
     2012-07-14 11:07:38.361 testMem str3 addr is 0x0
     2012-07-14 11:07:38.362 testMem str4 addr is 0x3540


     在栈中,内容相同的对象str1和str4,都分配在一个内存区域中,这点是c编译器的功能,有利于内存使用和效率。




     2012-07-14 11:07:38.363 testMem str1 retainCount is -1
     2012-07-14 11:07:38.364 testMem str2 retainCount is -1
     2012-07-14 11:07:38.365 testMem str3=;
     2012-07-14 11:07:38.366 testMem str1 retainCount is -1
     2012-07-14 11:07:38.367 testMem str3 retainCount is -1
     2012-07-14 11:07:38.367 testMem str3=;
     2012-07-14 11:07:38.368 testMem str2 retainCount is -1
     2012-07-14 11:07:38.369 testMem str3 retainCount is -1


     */
}
else
{




    NSMutableString * mstr1=[ initWithString:@"welcome"];
    NSMutableString * mstr2=[[NSMutableString alloc] initWithString:@"mlgb"];
    NSMutableString * mstr3;
    NSMutableString * mstr4=[[NSMutableString alloc] initWithString:@"welcome"];


    NSLog(@"mstr1 addr is %p",mstr1);
    NSLog(@"mstr2 addr is %p",mstr2);
    NSLog(@"mstr3 addr is %p",mstr3);
    NSLog(@"mstr4 addr is %p",mstr4);


    NSLog(@"mstr1 retainCount is %i",);
    NSLog(@"mstr2 retainCount is %i",);
    //NSLog(@"mstr3 retainCount is %i",);


    mstr3=;
    NSLog(@"mstr3=;");


    NSLog(@"mstr1 retainCount is %i",);
    NSLog(@"mstr3 retainCount is %i",);
    NSLog(@"mstr3 addr is %p",mstr3);


    mstr3=;
    NSLog(@"mstr3=;");
    NSLog(@"mstr2 retainCount is %i",);
    NSLog(@"mstr3 retainCount is %i",);
    NSLog(@"mstr3 addr is %p",mstr3);


    /*


     2012-07-14 11:07:36.652 testMem mstr1 addr is 0x68706b0
     2012-07-14 11:07:36.655 testMem mstr2 addr is 0x6876040
     2012-07-14 11:07:36.656 testMem mstr3 addr is 0x2a35
     2012-07-14 11:07:36.657 testMem mstr4 addr is 0x686fbf0


     2012-07-14 11:07:36.657 testMem mstr1 retainCount is 1
     2012-07-14 11:07:36.658 testMem mstr2 retainCount is 1


     2012-07-14 11:07:36.659 testMem mstr3=;


     2012-07-14 11:07:36.660 testMem mstr1 retainCount is 2
     2012-07-14 11:07:36.660 testMem mstr3 retainCount is 2


     2012-07-14 11:07:36.661 testMem mstr3 addr is 0x68706b0


     2012-07-14 11:07:36.662 testMem mstr3=;


     2012-07-14 11:07:36.663 testMem mstr2 retainCount is 2
     2012-07-14 11:07:36.663 testMem mstr3 retainCount is 2
     2012-07-14 11:07:36.664 testMem mstr3 addr is 0x6876040




     */




}


self.i_test=self.i_test+1;


}




简而言之,引用计数实际上是指向其内存区域的指针数,从内存块的角度去理解,就很容易理解了。
页: [1]
查看完整版本: iOS中引用计数内存管理机制分析