黑马程序员--Objective-C——内存管理二

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一、set方法的内存管理

接着上篇博文的例子,为Person增加一个属性_age和它的getset方法。在main.m中声明一新书。如果我们想给Person换一本新书。按照我们的思路,代码是这样的

 

<span style="background-color: rgb(255, 255, 255);">#import <Foundation/Foundation.h>
#import <a target=_blank class="gpxyarsm" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a>.h"
#import "Person.h"
 
int main(int argc, const char * argv[])
{
    // 创建一本书b1
   <a target=_blank class="gpxyarsm" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a> *b1 = [<a target=_blank class="gpxyarsm" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a> alloc] init];
    b1.price = 20;
    // 创建一个人p
    Person *p = [[Person alloc] init];
    p.age = 21;
    // p拥有b1
    p.book = b1;
    // 创建新书b2
    Book *b2 = [[Book alloc] init];
    b2.price = 50;
    // p换成新书b2
    p.book = b2;
    
    // 释放对象
    [b2 release];
    b2 = nil;
    [b1 release];
    b1 = nil;
    [p release];
    p = nil;
    return 0;
}</span>


运行后发现,我们创建了3个对象,却只有两个对象被回收了!之前那本旧书对象没有被回收。这是为什么呢?

我们之前的代码是没有问题的,加了一本新书就出了问题,所以问题就出在p.book=b2;这句话上。分析每个对象的对象计数器。

<span style="background-color: rgb(255, 255, 255);">    // 创建一本书b1,b1-1
    Book *b1 = [[Book alloc] init];
    b1.price = 20;
    // 创建一个人p,p1-1
    Person *p = [[Person alloc] init];
    p.age = 21;
    // p拥有b1,b1-2
    p.book = b1;
    // 创建新书b2,b2-1
    Book *b2 = [[Book alloc] init];
    b2.price = 50;
    // p换成新书b2,b2-2
    p.book = b2;
    
    // 释放对象,b2-1
    [b2 release];
    b2 = nil;
    // b1-1
    [b1 release];
    b1 = nil;
    // p-0, b2-0
    [p release];</span>

 b1运行到最后计数器的值是1,其他的对象都变成了0。原因就在与换书的时候没有release旧书。

解决方法:在Personset方法中的内容前加入[_car release];

 

这样,3个对象就都被释放了。


上面的代码看似没有问题了,其实还是有一些漏洞。

先开启僵尸对象检测。点击左上角的项目名称,选择Edit Scheme

 

 

勾选“Enable Zommbie Objects”启用僵尸对象

 

在现实生活中,我们有时候先不想要一个东西,就把这个东西丢了,丢了之后后悔了又想要了。但是在程序中,这样做就会出错。

<span style="background-color: rgb(255, 255, 255);">int main(int argc, const char * argv[])
{
    Person *p = [[Person alloc] init];
    p.age = 20;
   <a target=_blank class="gpxyarsm" href="#" title="Click to Continue > by MacVx"> book<img src="http://cdncache-a.akamaihd.net/items/it/img/arrow-10x10.png" alt="" /></a> *b = [[Book alloc] init];
    b.price = 30;
    
    p.book = b;
    [b release];
    p.book = b;
    [b release];
    [p release];
    return 0;
}</span>


 

运行发现控制台报了一个经典错误,“message sent to deallocated instance”,这句话的意思是把消息发送给了一个已经销毁的对象,也就是僵尸对象。

同之前一样,分析对象的引用计数器

 

此时的book_book都是b调用[book reatin]方法之前,b的计数器已经变成0了,对象b也被销毁。所以执行一个不存在的对象的方法出错了!

解决方法:在执行[_book release]前加入判断

<span style="background-color: rgb(255, 255, 255);">if (book != _book)
{
        [_book release];
}</span>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值