(iOS)手动内存管理01

来源:互联网 发布:矩阵论答案 程云鹏 编辑:程序博客网 时间:2024/05/17 06:25
    Person * person = [[Personalloc]init];
    person.
age =23;
   
NSLog(@"%@",person);
   
    [person
release];
   
//NSLog(@"retainCount = %lu",(unsigned long)person.retainCount);
    [personrun];

上面的代码有一个很有意思的地方,研究主题是手动的内存管理。当代码执行[person relase]的时候,person对象的retainCount值应该为0了,本应该会被销毁的对象,这个时候系统竟然可以调用person的run方法,后来查了一下,这主要是XCode一个问题,当XCode编译器发现person对象的retainCount值为0的时候,并不会去立刻释放该对象。但是如果是执行到
     NSLog(@"retainCount = %lu",(unsigned long)person.retainCount);
这一行代码的时候,系统又会立刻报出一个野指针操作的异常。
带着这一个问题到网上看了一下,网友给出的答案是

你所谓的销毁根本没有发生,release函数的主要作用是将引用计数器减去1,而不是释放这个对象,当这个对象的引用计数器变为0的时候,系统会在一个合适的时机去销毁这块内存,这个合适的时机是根据你的程序的情况来定的,可能是一个函数调用完成,也可能是一个线程结束,也可能是一次runloop完成,也可能是程序退出,所以,我们并不能确认到底在什么地方一个已经release的东西会被销毁,对于你这段代码,能肯定的是,当retutn 0 以后,这个变量应该是被销毁掉了,所以我们当我们release了不表示这个变量被销毁了,而是它不能被安全的访问了...不能被安全的访问不代表不能访问。。。

最后我总结一下
当对象的retainCount值为0的时候,该对象的变量是被封锁起来的,也就是说该对象分配的内存并没有立刻被系统回收,而是被保护起来,所以变量没有被销毁,但是同时也不能够被访问。但是,为什么能访问对象的方法呢?原因很简单,方法并不是分配在对象内存区域块的,而是类的内存块,所以访问该方法还是可以执行的。但是该方法要访问对象的变量呢?
结果我又试了一下,发现竟然是可以访问该变量的。
所以我在想,是不是指针不能指向该内存的变量,但是类区的方法是可以访问该变量。

进一步的分析,结合了培训老师的知识点
/*
被系统回收的对象,我们称之为僵尸对象(僵尸对象的变量是保护起来的)
默认情况下,XCode为了提高编码效率,不会时时检查僵尸对象
导致了我们调用已经被销毁回收的对象的成员变量的时候,有时不会出现下面的错误,有时会出现下面的错误。
EXC_BAD_ACCESS 访问了不可访问的内存空间

1,设置XCode时时检查僵尸对象
1.1,点击左上角,工程名,出现Edit Scheme
1.2,Run 。。。 Debug
1.3,Diagnostics,把Enable Zombie Objects,勾选上。
//但是实际开发中,还是把这个勾选取消。
*/

最后实验了一下,当执行到[person run]方法的时候,程序就出现错误了。
1 0