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

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

在 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",[str1 retainCount]);

NSLog(@"str2 retainCount is %i",[str2 retainCount]);

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

str3=[str1 retain];

NSLog(@"str3=[str1 retain];");

NSLog(@"str1 retainCount is %i",[str1 retainCount]);

NSLog(@"str3 retainCount is %i",[str3 retainCount]);

str3=[str2 retain];

NSLog(@"str3=[str2 retain];");

NSLog(@"str2 retainCount is %i",[str1 retainCount]);

NSLog(@"str3 retainCount is %i",[str2 retainCount]);

/*

结果如下:

2012-07-14 11:07:38.358 testMem[878:f803] str1 addr is 0x3540

2012-07-14 11:07:38.360 testMem[878:f803] str2 addr is 0x0

2012-07-14 11:07:38.361 testMem[878:f803] str3 addr is 0x0

2012-07-14 11:07:38.362 testMem[878:f803] str4 addr is 0x3540

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

2012-07-14 11:07:38.363 testMem[878:f803] str1 retainCount is -1

2012-07-14 11:07:38.364 testMem[878:f803] str2 retainCount is -1

2012-07-14 11:07:38.365 testMem[878:f803] str3=[str1 retain];

2012-07-14 11:07:38.366 testMem[878:f803] str1 retainCount is -1

2012-07-14 11:07:38.367 testMem[878:f803] str3 retainCount is -1

2012-07-14 11:07:38.367 testMem[878:f803] str3=[str2 retain];

2012-07-14 11:07:38.368 testMem[878:f803] str2 retainCount is -1

2012-07-14 11:07:38.369 testMem[878:f803] str3 retainCount is -1

*/

}

else

{

NSMutableString * mstr1=[[NSMutableString alloc] initWithString:@"welcome"];

NSMutableString* mstr2=[[NSMutableStringalloc]initWithString:@"mlgb"];

NSMutableString* mstr3;

NSMutableString* mstr4=[[NSMutableStringalloc]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",[mstr1 retainCount]);

NSLog(@"mstr2 retainCount is %i",[mstr2 retainCount]);

//NSLog(@"mstr3 retainCount is %i",[mstr3 retainCount]);

mstr3=[mstr1 retain];

NSLog(@"mstr3=[mstr1 retain];");

NSLog(@"mstr1 retainCount is %i",[mstr1 retainCount]);

NSLog(@"mstr3 retainCount is %i",[mstr3 retainCount]);

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

mstr3=[mstr2 retain];

NSLog(@"mstr3=[mstr2 retain];");

NSLog(@"mstr2 retainCount is %i",[mstr1 retainCount]);

NSLog(@"mstr3 retainCount is %i",[mstr2 retainCount]);

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

/*

2012-07-14 11:07:36.652 testMem[878:f803] mstr1 addr is 0x68706b0

2012-07-14 11:07:36.655 testMem[878:f803] mstr2 addr is 0x6876040

2012-07-14 11:07:36.656 testMem[878:f803] mstr3 addr is 0x2a35

2012-07-14 11:07:36.657 testMem[878:f803] mstr4 addr is 0x686fbf0

2012-07-14 11:07:36.657 testMem[878:f803] mstr1 retainCount is 1

2012-07-14 11:07:36.658 testMem[878:f803] mstr2 retainCount is 1

2012-07-14 11:07:36.659 testMem[878:f803] mstr3=[mstr1 retain];

2012-07-14 11:07:36.660 testMem[878:f803] mstr1 retainCount is 2

2012-07-14 11:07:36.660 testMem[878:f803] mstr3 retainCount is 2

2012-07-14 11:07:36.661 testMem[878:f803] mstr3 addr is 0x68706b0

2012-07-14 11:07:36.662 testMem[878:f803] mstr3=[mstr2 retain];

2012-07-14 11:07:36.663 testMem[878:f803] mstr2 retainCount is 2

2012-07-14 11:07:36.663 testMem[878:f803] mstr3 retainCount is 2

2012-07-14 11:07:36.664 testMem[878:f803] mstr3 addr is 0x6876040

*/

}

self.i_test=self.i_test+1;

}

简而言之,引用计数实际上是指向其内存区域的指针数,从内存块的角度去理解,就很容易理解了。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航