android sp和wp

android sp和wp

android的sp是指strong pointer wp则是weak pointer,引入他们的目的是解决C++中容易出现的空指针、野指针、new 和 delete导致的内存泄漏或者访问出错问题。

 

无论时sp还是wp,其目标对象都需要继承refBase类,改为为其子类提供了引用计数变量mstrong 、mweak以及用于对变量进行操作的operation 函数;

 

对于sp指针,在创建是赋值或者new赋值时,会调用目标对象的incStrong函数,增加mstrong的引用计数,同时mweak也会加1:

sp<T> pA1 = new T

如上(frameworks/native/include/utils/StrongPointer.h):

(frameworks/native/libs/utils/RefBase.cpp):

而在已移除是会减1:

(frameworks/native/libs/utils/RefBase.cpp)发现计数为0后还会自动释放delete 对象:

 

 

那么wp的目的是什么呢,在有些场景下比如父类CDad持有子类CChild,同时CChild也持有CDad这个时候,引用计数mstrong不会变为0,这样就导致父类和子类一直无法释放,形成死锁,所以正对这种情况开发了wp,并约定父类使用sp,子类则使用wp,当mstrong计数为0时无论mweak是否为0,都可以delete目标对象(refbase子类)。不过如果这时候wp访问delete的目标对象就会放生访问越界,所以android规定wp必须升级为sp后才能访问目标对象。

看一下refbase在decWeak函数中,当mweak的计数为0是会有哪些动作:

首先mWeak 减1,如果c !=1 即mWeak不为0直接返回;

如果为0,进入下一步判断:

(impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG

如果为真,表示目标现在由强应用控制,需要mstrong为0是释放对象,但是

mpl->mStrong == INITIAL_STRONG_VALUE

如上表明从未有过强引用,那么此时需要释放对象delete mbase,否者只需要释放

weakref_impl这个计数器

如果if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK)为真

此时为wp控制,则释放目标对象:

  delete impl->mBase;

 

这个mflags目前来看在初始化时都为0也就是  OBJECT_LIFETIME_STRONG,android提供了函数修改这个值extendObjectLifetime

 

 

如下是wp/sp与refbase的类图,可以参考理解:

问题:

前面提到在decWeak函数中,mWeak计数为0时,在强引用下,且强引用不为0时,会delete impl,这个impl应该是refbase中的mRefs:

如果在这边释放,在使用refBase中的decStrong去释放mBase的时候也使用该变量

这样访问的不就是一个不存在的内存区域吗,应该会crash吧!

 

能够避免该问题,就需要mWeak的计数值只能比mStrong大,不能小;

就目前代码来看,在incStrong是同时会增加mWeak、mStrong,但是incWeak时只会增加mWeak,这么看来mWeak的计数值只会比mStrong大,不会小,那么就不会出现这样的crash。

那为什么一定要在decWeak去释放mRefs呢,看一下RefBase的析构函数,mWeak =0 才能delete mRefs ,不得不说android的工程师真是NB:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值