[试验]在Objective-C中 NSString并不受引用计数器机制管理

众所周知,在Objective-C中的内存管理是通过一种叫做“引用计数器”的机制管理的。

举例, 当我声明了一个新的实例

NSData *data = [[NSData alloc] init]

现在,内存中有一个NSData类型的对象,名叫data。它的引用计数器的值为1. 如果我再次引用它的时候,他的引用计数值会+1变为2.

使用完毕后需要调用

[data release];

来使引用计数-1.  当该值为零的时候,系统会将data实例回收掉并释放内存。

但刚刚我在Cocoachina上看到一篇文章,作者询问在这种情况下会不会造成内存泄露?为什么不会崩溃?

代码如下:

NSString *str = [[NSString alloc] initWithString:@"ABC"];

str = @"123";

[str release];

NSLog(@"%@".str);
 
首先,咱们先对这段代码进行分析。
第一句 声明了一个NSString类型的实例 str, 并将其初始化init后赋值为@"ABC"
第二行,将str的指针指向了一个常量@"123"。 理论上讲在第一行初始化的@"ABC"没有任何任何指针指向了。 所以造成了内存泄露
然后第三行, 将str的引用计数-1 
第四行输出str的值  为123.

首先回答为什么不会崩溃, 因为第三行的release 实际上是release了一个常量@"123"  而作为常量,其默认的引用计数值是很大的(100k+)
不信的话你们可以试试这句
NSLog(@"retainCount = %d",[@"123" retainCount]);
最终的输出值会是一个很大很大的数。  所以单单一个release是不会将其释放掉的。

然后再回答这样会不会造成内存泄露。
其实…………理论上讲 会!  
但是实际上,Objective-C对NSString类型有特殊照顾。所有的NSString的引用计数器默认初始值都会非常非常大。
同学们可以自行实验验证一下。
如果例子中的不是NSString而是其他类型 例如NSData、NSNumber等等等。。。
则肯定会造成内存泄露。
内存泄露的后果在短时间内不会显现。 但以长远角度来看,后果是非常非常严重的。
同学们一定要避免内存泄露的发生。
若想这样,那就必须要养成良好的编码习惯。
引用官方文档的一句话说,
谁引用了谁负责释放
说白了就是谁Init、Retain、Copy了。 谁负责Release。
理论上讲,你代码中的init+retain+copy的个数 应该等于release的个数。
这样才可以最大程度上的避免内存泄露的发生。

好了,欢迎大家和我一起讨论各种问题。
只要在下方留言即可。我会即时回复的。

:)

 

 

2 thoughts on “[试验]在Objective-C中 NSString并不受引用计数器机制管理

  1. Hey there! This is kind of off topic but I need some advice from
    an established blog. Is it tough to set up your own blog?
    I’m not very techincal but I can figure things out pretty quick. I’m thinking about setting up
    my own but I’m not sure where to begin. Do you have any ideas or suggestions? Cheers

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*