众多周知,指针在C/C++是一个很重要的手段,但是也是最让人麻烦的东西,容易出现空指针,或者内存泄漏,无非是new了一个对象,没有对应的delete,长时间运行导致系统崩溃!

在android系统中其实也有这个指针这个概念,只不过被用另外的一种安全机制弥补以上的麻烦。


一.概念:

android的中间层frameworks中的JNI以及往下的libraries 运行库层大部分使用的是C++来写的,目的是为了提高效率,在这些地方就需要用到指针了!

android 提供了一套机制为智能指针:

智能指针本身为一个对象,是一个模板类,可以当作一个控制类。有 sp wp 这两个类,后面介绍。

通过对指针指向的对象进行引用计数控制,来决定delete对象,不会遗漏new出来无用的对象,只要还有指针还指向目标对象,那么就不会delete该对象 也杜绝了指针指空的现象!


智能指针用法分三种类型:

1.轻量级指针

2.强指针

3.弱指针



二.轻量级指针:

目标对象的引用计数类为:/frameworks/native/include/utils/RefBase.h 中的 LightRefBase 类,也就是说智能指针指向的对象是继承于LightRefBase这个父类或者间接父类的!

template <class T>class LightRefBase{public:    inline LightRefBase() : mCount(0) { }    inline void incStrong(const void* id) const {        android_atomic_inc(&mCount);    }    inline void decStrong(const void* id) const {        if (android_atomic_dec(&mCount) == 1) {            delete static_cast<const T*>(this);        }    }...}

可以看到由mCount 一个变量来计数,初始为0,有incStrong decStrong 这个两个方法 来操作 mCount 。

这个计数类比较简单,接口方法只有 sp 类才有,所以我的理解 轻量级的指针只是因为计数类比较简单,智能指针控制类和强指针的类型一样都是 sp!

看看 sp 类:

android4.2 在/frameworks/native/include/utils/StrongPointer.h中定义.

class sp{public:    inline sp() : m_ptr(0) { }    sp(T* other);    sp(const sp<T>& other);    template<typename U> sp(U* other);    template<typename U> sp(const sp<U>& other);    ~sp();...}

sp 就是一个智能指针对象,当指向某一个对象的时候,就会创建,当不需要指向某一个对象的时候,也就是这个指针销毁的时候,分别会调用构造函数和析构函数。

看看sp 指针类的构造和析构:

template<typename T>sp<T>::sp(T* other): m_ptr(other)  {    if (other) other->incStrong(this);  }template<typename T>sp<T>::sp(const sp<T>& other): m_ptr(other.m_ptr)  {    if (m_ptr) m_ptr->incStrong(this);  }

template<typename T>sp<T>::~sp(){    if (m_ptr) m_ptr->decStrong(this);}

可以看到分别调用的是引用的对象的 incStrongdecStrong 分别对应 LightRefBase的计数加1 和 减1 ,可以看到当mCount=1 的时候 再 decStrong 就会 delete对象!



三.强指针:

和轻量级指针不同,强指针用RefBase类计数,同样需要用强指针的也得继承了这个类,也在/frameworks/native/include/utils/RefBase.h中定义:

class RefBase{public:            void            incStrong(const void* id) const;            void            decStrong(const void* id) const;                void            forceIncStrong(const void* id) const;            //! DEBUGGING ONLY: Get current strong ref count.            int32_t         getStrongCount() const;    class weakref_type    {    public:        RefBase*            refBase() const;                void                incWeak(const void* id);        void                decWeak(const void* id);                // acquires a strong reference if there is already one.        bool                attemptIncStrong(const void* id);                // acquires a weak reference if there is already one.        // This is not always safe. see ProcessState.cpp and BpBinder.cpp        // for proper use.        bool                attemptIncWeak(const void* id);        //! DEBUGGING ONLY: Get current weak ref count.        int32_t             getWeakCount() const;        //! DEBUGGING ONLY: Print references held on object.        void                printRefs() const;        //! DEBUGGING ONLY: Enable tracking for this object.        // enable -- enable/disable tracking        // retain -- when tracking is enable, if true, then we save a stack trace        //           for each reference and dereference; when retain == false, we        //           match up references and dereferences and keep only the        //           outstanding ones.                void                trackMe(bool enable, bool retain);    };                weakref_type*   createWeak(const void* id) const;                        weakref_type*   getWeakRefs() const;            //! DEBUGGING ONLY: Print references held on object.    inline  void            printRefs() const { getWeakRefs()->printRefs(); }            //! DEBUGGING ONLY: Enable tracking of object.    inline  void            trackMe(bool enable, bool retain)    {        getWeakRefs()->trackMe(enable, retain);    }    typedef RefBase basetype;protected:                            RefBase();    virtual                 ~RefBase();    //! Flags for extendObjectLifetime()    enum {        OBJECT_LIFETIME_STRONG  = 0x0000,        OBJECT_LIFETIME_WEAK    = 0x0001,        OBJECT_LIFETIME_MASK    = 0x0001    };                void            extendObjectLifetime(int32_t mode);                //! Flags for onIncStrongAttempted()    enum {        FIRST_INC_STRONG = 0x0001    };        virtual void            onFirstRef();    virtual void            onLastStrongRef(const void* id);    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);    virtual void            onLastWeakRef(const void* id);private:    friend class ReferenceMover;    static void moveReferences(void* d, void const* s, size_t n,            const ReferenceConverterBase& caster);private:    friend class weakref_type;    class weakref_impl;                                RefBase(const RefBase& o);            RefBase&        operator=(const RefBase& o);        weakref_impl* const mRefs;};

这个类有点复杂,知道几个重要的函数就可以了,这个计数类也提供了 incStrongdecStrong这两个控制计数的函数

所谓强指针,肯定是比轻量级的复杂,包含了轻量级的简单计数以外,还区分了计数的类型,分强引用的计数和弱引用的计数,这个两个计数器的值都能起到决定是否delete的作用,

这样做的原因是因为,如果在两个对象之间。互相通过指针引用了对象,当两个对象都不需要用到的时候,就无法单独回收一个对象,定义一个规则 在某个对象的强引用计数为0的时候 不管弱引用多少 都delete 就能解决这一问题

在嵌套引用中就需要设置delete 到底依赖规则,依赖强计数 还是 弱计数 !

这两种计数的变量在RefBase类里面由weakref_impl 类提供 ,也就是 mRefs,看看weakref_impl类:

/frameworks/base/libs/utils/RefBase.cpp中:

class RefBase::weakref_impl : public RefBase::weakref_type{public:    volatile int32_t    mStrong;    volatile int32_t    mWeak;    RefBase* const      mBase;    volatile int32_t    mFlags;#if !DEBUG_REFS    weakref_impl(RefBase* base)        : mStrong(INITIAL_STRONG_VALUE)        , mWeak(0)        , mBase(base)        , mFlags(0)    {    }...}



可以看到前面两个就是两个计数变量,mBase代表这个类对应的RefBase类,

而mFlags就是上面说的依赖规则了,怎么来判定处理前面的两个计数变量!构造函数可以看到 默认为0。对应一个枚举,在RefBase类中的weakref_type类:

    enum {        OBJECT_LIFETIME_STRONG  = 0x0000,        OBJECT_LIFETIME_WEAK    = 0x0001,        OBJECT_LIFETIME_MASK    = 0x0001    };



同轻量级一样,在智能指针指向对象的时候,调用指针的构造,这里强指针就是通过 sp 实际调用到对象的incStrong

也就是 RefBase::incStrong:

void RefBase::incStrong(const void* id) const{    weakref_impl* const refs = mRefs;    refs->incWeak(id);        refs->addStrongRef(id);    const int32_t c = android_atomic_inc(&refs->mStrong);    ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);...}

android4.2 在incWeak 里面增加了弱引用计数,然后addStrongRef再增加了强计数。强弱计数都+1.

实际处理函数为android_atomic_inc(&refs->mStrong)


同样在销毁的时候调用RefBase::decStrong:

void RefBase::decStrong(const void* id) const{    weakref_impl* const refs = mRefs;    refs->removeStrongRef(id);    const int32_t c = android_atomic_dec(&refs->mStrong);#if PRINT_REFS    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);#endif    ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);    if (c == 1) {        refs->mBase->onLastStrongRef(id);        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {            delete this;        }    }    refs->decWeak(id);}
实际处理函数为 android_atomic_dec(&refs->mStrong)

可以看到在操作完强计数的时候,会做判断,如果是到0了,然后依赖的处理规则又是强引用,那么就delete这个对象!


不然就往下处理弱引用计数decWeak:

void RefBase::weakref_type::decWeak(const void* id){    weakref_impl* const impl = static_cast<weakref_impl*>(this);    impl->removeWeakRef(id);    const int32_t c = android_atomic_dec(&impl->mWeak);    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);    if (c != 1) return;    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {        // This is the regular lifetime case. The object is destroyed        // when the last strong reference goes away. Since weakref_impl        // outlive the object, it is not destroyed in the dtor, and        // we'll have to do it here.        if (impl->mStrong == INITIAL_STRONG_VALUE) {            // Special case: we never had a strong reference, so we need to            // destroy the object now.            delete impl->mBase;        } else {            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);            delete impl;        }    } else {        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}        impl->mBase->onLastWeakRef(id);        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference            // is gone, we can destroy the object.            delete impl->mBase;        }    }}

一样的,做了判断,如果发现到0了然后规则是弱引用处理,就delete



四.弱指针:

弱指针所用的计数类和强指针的一样为RefBase这个类。控制的智能指针不一样而已 为 wp 类,定义在/frameworks/native/include/utils/RefBase.h

template <typename T>class wp{public:    typedef typename RefBase::weakref_type weakref_type;        inline wp() : m_ptr(0) { }    wp(T* other);    wp(const wp<T>& other);    wp(const sp<T>& other);    template<typename U> wp(U* other);    template<typename U> wp(const sp<U>& other);    template<typename U> wp(const wp<U>& other);    ~wp();...    // promotion to sp        sp<T> promote() const;...}

调用同上面的一样,直接看构造和析构函数:

template<typename T>wp<T>::wp(T* other)    : m_ptr(other){    if (other) m_refs = other->createWeak(this);}template<typename T>wp<T>::~wp(){    if (m_ptr) m_refs->decWeak(this);}

分别调用到RefBase类里面的实现函数:

构造的

RefBase::weakref_type* RefBase::createWeak(const void* id) const{    mRefs->incWeak(id);    return mRefs;}

这里的mRefs 是weakref_impl类的对象,上面有说过的,调到:


void RefBase::weakref_type::incWeak(const void* id){    weakref_impl* const impl = static_cast<weakref_impl*>(this);    impl->addWeakRef(id);    const int32_t c = android_atomic_inc(&impl->mWeak);    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);}

这里只是 弱引用计数 +1


析构的

直接调用到:

RefBase::weakref_type::decWeak

同上!


另外弱指针有一个特性,就是无法直接操作目标对象,弱指针类没有重载*和->操作符号!


弱指针可以通过promote()方法提升为强指针!


实现函数:RefBase::weakref_type::attemptIncStrong

bool RefBase::weakref_type::attemptIncStrong(const void* id){    incWeak(id);        weakref_impl* const impl = static_cast<weakref_impl*>(this);        int32_t curCount = impl->mStrong;    ALOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",               this);    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {        if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {            break;        }        curCount = impl->mStrong;    }        if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {        bool allow;        if (curCount == INITIAL_STRONG_VALUE) {            // Attempting to acquire first strong reference...  this is allowed            // if the object does NOT have a longer lifetime (meaning the            // implementation doesn't need to see this), or if the implementation            // allows it to happen.            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK                  || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);        } else {            // Attempting to revive the object...  this is allowed            // if the object DOES have a longer lifetime (so we can safely            // call the object with only a weak ref) and the implementation            // allows it to happen.            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK                  && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);        }        if (!allow) {            decWeak(id);            return false;        }        curCount = android_atomic_inc(&impl->mStrong);        // If the strong reference count has already been incremented by        // someone else, the implementor of onIncStrongAttempted() is holding        // an unneeded reference.  So call onLastStrongRef() here to remove it.        // (No, this is not pretty.)  Note that we MUST NOT do this if we        // are in fact acquiring the first reference.        if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {            impl->mBase->onLastStrongRef(id);        }    }        impl->addStrongRef(id);#if PRINT_REFS    ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);#endif    if (curCount == INITIAL_STRONG_VALUE) {        android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);        impl->mBase->onFirstRef();    }        return true;}


但是提升为强指针是要看目前弱指针对象是否已经delete,还要看对象有没有设置一些属性导致不被允许提升为强指针

一种情况是 对象整在被其它强指针引用 强引用肯定大于0 可以提升为强指针 然后增加对象强引用计数


第二种情况:

如果没有被其它的强指针引用而且强引用计数等于INITIAL_STRONG_VALUE就要满足:

allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK                  || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);

否则就要满足:

allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK&& impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);



如果allow为false 就代表不能提升为强指针,那么就要减小目标对象的弱引用计数,因为attempIncStrong 开头就直接增加了弱引用计数!

如果满足条件,往下就增加强引用计数.



五.强弱指针使用范例:

借用一个写的比较形象的范例:


#include <stdio.h>#include <utils/RefBase.h>#define INITIAL_STRONG_VALUE (1<<28)using namespace android;class WeightClass : public RefBase{public:        void printRefCount()        {                int32_t strong = getStrongCount();                weakref_type* ref = getWeakRefs();                printf("-----------------------\n");                printf("Strong Ref Count: %d.\n", (strong  == INITIAL_STRONG_VALUE ? 0 : strong));                printf("Weak Ref Count: %d.\n", ref->getWeakCount());                printf("-----------------------\n");        }};class StrongClass : public WeightClass{public:        StrongClass()        {                printf("Construct StrongClass Object.\n");        }        virtual ~StrongClass()        {                printf("Destory StrongClass Object.\n");        }};class WeakClass : public WeightClass{public:        WeakClass()        {                extendObjectLifetime(OBJECT_LIFETIME_WEAK);                printf("Construct WeakClass Object.\n");        }        virtual ~WeakClass()        {                printf("Destory WeakClass Object.\n");        }};void TestStrongClass(StrongClass* pStrongClass){        wp<StrongClass> wpOut = pStrongClass;        pStrongClass->printRefCount();        {                sp<StrongClass> spInner = pStrongClass;                pStrongClass->printRefCount();        }        sp<StrongClass> spOut = wpOut.promote();        printf("spOut: %p.\n", spOut.get());}void TestWeakClass(WeakClass* pWeakClass){        wp<WeakClass> wpOut = pWeakClass;        pWeakClass->printRefCount();        {                sp<WeakClass> spInner = pWeakClass;                pWeakClass->printRefCount();        }        pWeakClass->printRefCount();        sp<WeakClass> spOut = wpOut.promote();        printf("spOut: %p.\n", spOut.get());}int main(int argc, char** argv){        printf("Test Strong Class: \n");        StrongClass* pStrongClass = new StrongClass();        TestStrongClass(pStrongClass);        printf("\nTest Weak Class: \n");        WeakClass* pWeakClass = new WeakClass();        TestWeakClass(pWeakClass);        return 0;}


跑起来的结果:

Test Strong Class: Construct StrongClass Object.-----------------------Strong Ref Count: 0.Weak Ref Count: 1.----------------------------------------------Strong Ref Count: 1.Weak Ref Count: 2.-----------------------Destory StrongClass Object.spOut: 0x0.

可以看到首先是用的一个弱指针去指向对象,所以对象的强引用计数为0 弱引用计数为1

然后中途用一个强指针指向对象,对象的两个引用计数全部加1

退出大括号,销毁强指针,因为默认的强指针是依赖强引用的,上面有说 mFlag 设的是0 ,所在这个时候发现对象的强引用从1变为0了,就delete对象

最后再来用之前的弱指针提升到强指针,因为对象不存在了,所以失败 返回 0x0.


Test Weak Class: Construct WeakClass Object.-----------------------Strong Ref Count: 0.Weak Ref Count: 1.----------------------------------------------Strong Ref Count: 1.Weak Ref Count: 2.----------------------------------------------Strong Ref Count: 0.Weak Ref Count: 1.-----------------------spOut: 0xa528.Destory WeakClass Object.

这个弱指针的测试前面和上面一样,不同的就是在对象创建的时候 设置了引用计数的依赖规则为 依赖弱引用计数!

所以在中途退出大括号时,不会delete

这个时候提升强指针也满足上面说到过的条件,所以返回0xa528

在程序退出时,弱指针也销毁,这个时候,弱引用计数为0 ,delete 对象!


到这里学习分析完毕!

撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/30070775









更多相关文章

  1. Android:子线程向UI主线程发送消息
  2. Android(安卓)MVVM
  3. Android在开发中的实用技巧之Parcelable的使用以及如何传递复杂
  4. Android(安卓)JSON:Gson,FastJson解析库的使用和对比分析
  5. 信息提醒之Notification,兼容全部SDK-更新中
  6. Android(安卓)SDK中的强大工具——Monitor(一)
  7. OSG 坑爹的Android(安卓)example
  8. Sensor系列之aDSP端Sensor Driver流程
  9. Android基于HTTP网络编程总结浅析

随机推荐

  1. Android中的动画研究(一)
  2. Android(安卓)显示原理简介
  3. Android初级开发(八)——手机多媒体—音频
  4. FirefoxOS 系统进程初步分析 底层系统继
  5. 如何构建Android(安卓)MVVM 应用框架
  6. android平台现状分析
  7. [Android] 点击listView的item无响应【解
  8. Android之permission权限列表2-另一篇文
  9. android架构
  10. Android设备预计将超微软