Android智能指针浅析(win32 debug)

来源:互联网 发布:淘宝怎么看评价几星 编辑:程序博客网 时间:2024/05/16 11:48
Android智能指针浅析(win32 debug)

============= 目录结构:===========

(一)引言

(二)摘录class RefBase的定义
(三)摘录class RefBase::weakref_impl的定义
(四)摘录模板类template <typename T> class sp 的定义
(五)摘录模板类template <typename T> class wp的定义
(六)samples解释(两个范例)
(七)使用方法

(八)总结

============= ====================

(一)引言

          基于C/C++ 开发的程序员都有体会,关于内存的分配和释放必须匹配,而Java程序开发人员却无此忧虑,这归功于Java语言的“垃圾自动回收”机制。C语言中使用malloc/free,C++中使用new/delete。这些动作必须由程序员显示的用代码去控制,一不小心就会发生如下状况:

1)分配了内存空间,使用完后,忘了释放,造成内存泄露(memory leak);

          2)释放后的内存空间,透过指针再去使用时,发生系统异常。在Linux环境下是signal 11错误,即“段错误”(Segmentation Fault)。

          故此,C++ 中提出了“智能指针”,试图将程序员解放出来去做其它一些更有意义的事情。同样,Google公司针对Android系统自身的需要,设计一套自己的智能指针,即Android native端代码中随处可见的sp<XXX>和wp<XXX>,XXX是对象的类,sp和wp是模板类(关于模板,不熟悉的童鞋需要复习下C++中模板章节)。sp和wp分别代表了强指针(strong pointer)和弱指针(weak pointer)。如果需要使用智能指针,XXX只需要继承自RefBase,并将析构函数声明为virtual 函数。

(二)摘录class RefBase的定义

// 所有需要利用Android自带的智能指针的wp/sp回收内存的class都必须继承自RefBase

class RefBase
{
public:

    void            incStrong(const void* id) const;

    void            decStrong(const void* id) const;

    void           forceIncStrong(const void* id) const;

 

    class weakref_type

    {

    public:

        RefBase*            refBase() const;

       

       void                incWeak(constvoid* id);

       void                decWeak(constvoid* id);

       

        // acquires a strong reference if thereis already one.

        bool                attemptIncStrong(const void*id);

       

        // acquires a weak reference if thereis already one.

        // This is not always safe. seeProcessState.cpp and BpBinder.cpp

        // for proper use.

        bool                attemptIncWeak(const void* id);

    };

   

    // 返回” 影子对象 “

    weakref_type*   createWeak(const void* id) const;

    weakref_type*   getWeakRefs() const;

 

protected:

    //! Flags for extendObjectLifetime()  //对象销毁策略判断标志enum类型定义

    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_tflags, const void* id);

    virtual void            onLastWeakRef(const void* id);

 

 

private:

    class weakref_impl; // 继承自RefBase:: weakref_type

  

    weakref_impl* const mRefs; // 很重要,可以称之为“影子对象”

}

(三)摘录class RefBase::weakref_impl的定义

#define INITIAL_STRONG_VALUE (1<<28)

 

classRefBase::weakref_impl : public RefBase::weakref_type

{

public:

volatile int32_t    mStrong; //强引用计数

volatile int32_t    mWeak;  // 弱引用计数

RefBase* const   mBase; // 指向其容器类RefBase

 

/* mFlags为对象销毁策略判断标志,若为0(OBJECT_LIFETIME_STRONG),强引用计数为0时便自动销毁目标对象。初始值为0

*/

 volatileint32_t    mFlags;


    weakref_impl(RefBase* base)

        :mStrong(INITIAL_STRONG_VALUE)

        , mWeak(0)

        , mBase(base)

        , mFlags(0)

    {

    }

……

}

 

【关于mFlags的说明】

// 对象销毁策略判断标志

    enum {

       OBJECT_LIFETIME_STRONG  = 0x0000,

       OBJECT_LIFETIME_WEAK    = 0x0001,

       OBJECT_LIFETIME_MASK    = 0x0001

    };

(1)若mFlags为0时(即OBJECT_LIFETIME_STRONG),强引用计数控制实际对象的生命周期,弱引用计数控制影子对象的生命周期。则强引用计数为0时,销毁实际对象。此种case,保险起见,使用wp时要由弱强(调用wp的promote()),以免收到segment fault信号;

(2)若mFlags为1时(OBJECT_LIFETIME_WEAK),强引用计数为0,弱引用计数不为0时,实际对象不会被delete。当弱引用计数减为0时,实际对象和影子对象会同时被delete;

(3)可以调用RefBase的extendObjectLifetime(int32_t mode)改变策略标志变量mFlags。

(四)摘录模板类template <typename T> class sp 的定义

template<typename T>

class sp

{

public:

    inline sp() : m_ptr(0) { }

 

    sp(T* other);

    sp(const sp<T>& other);

    template<typenameU> sp(U* other);

    template<typename U> sp(constsp<U>& other);

 

    ~sp();

 

    // Assignment

 

    sp& operator = (T* other);

    sp& operator = (const sp<T>&other);

 

    template<typename U> sp& operator= (const sp<U>& other);

    template<typename U> sp& operator= (U* other);

 

    //! Special optimization for use byProcessState (and nobody else).

    void force_set(T* other);

 

    // Reset

 

    void clear();

 

    // Accessors

 

    inline T&      operator* ()const  { return *m_ptr; }

    inline  T*     operator-> () const { return m_ptr; }

    inline  T*     get() const         { returnm_ptr; }

 

    // Operators

 

    COMPARE(==)

    COMPARE(!=)

    COMPARE(>)

    COMPARE(<)

    COMPARE(<=)

    COMPARE(>=)

 

private:   

    template<typename Y> friend class sp;

    template<typename Y> friend class wp;

    void set_pointer(T* ptr);

    T* m_ptr;  // 保存实际对象,实际对象内部包含了“影子对象”

};

(五)摘录模板类template <typename T> class sp 的定义

template<typename T>

class wp

{

public:

    typedef typename RefBase::weakref_typeweakref_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(constsp<U>& other);

    template<typename U> wp(constwp<U>& other);

 

    ~wp();

   

    // Assignment

 

    wp& operator = (T* other);

    wp& operator = (const wp<T>&other);

    wp& operator = (const sp<T>&other);

   

    template<typename U> wp& operator= (U* other);

    template<typename U> wp& operator= (const wp<U>& other);

    template<typename U> wp& operator= (const sp<U>& other);

   

    void set_object_and_refs(T* other,weakref_type* refs);

 

    // promotion to sp

   

    sp<T>promote() const;

 

    // Reset

   

    void clear();

 

    // Accessors

   

    inline weakref_type* get_refs() const { return m_refs; }

   

    inline T* unsafe_get() const { return m_ptr; }

 

    // Operators

 

    COMPARE_WEAK(==)

    COMPARE_WEAK(!=)

    COMPARE_WEAK(>)

    COMPARE_WEAK(<)

    COMPARE_WEAK(<=)

    COMPARE_WEAK(>=)

 

 

private:

    template<typename Y> friend class sp;

    template<typename Y> friend class wp;

 

    T*              m_ptr; //保存实际对象,构造函数传入

   weakref_type*   m_refs; // SP不同,WP显示地保存了“影子对象”

};

【说明】

       需要注意的是wp并没有重载“*”和“->”这两个操作符,所以需要先升级为强指针(通过调用promote()函数),才可以像正常指针一样访问实际对象的一些方法。但是,很有可能存在一种情况是,wp在升级成sp之前,实际对象已经被销毁,所以,pomote()后需要判断实际对象是否为0。

(六)关于强弱引用计数的samples解释(两个范例)

Sample1:创建一个ClassA的对象(ClassA继承自RefBase),并传给模板类sp(strong pointer, 强指针) ,通过在win32下的debug分解其运行过程:


1)ClassA的定义


2)new ClassA的执行动作

//调用RefBase的构造函数


//调动weakref_impl的构造函数


// 调用ClassA的构造函数


2)执行模板类sp的构造函数:template<typenameT> sp<T>::sp(T* other);

// 直接run,开始debug


// 调用模板类sp的构造函数,将pA赋给成员变量m_ptr


//调用pARefBase::incStrong()函数,强引用计数值和引用计数值分别+1


3)执行模板类sp的析构函数: template<typenameT> sp<T>::~sp();

// 模板类sp的对象spA的生命期即将结束


//调用模板类sp的析构函数


//调用pARefBase::decStrong(constvoid* id),删除ClassA的对象pA,释放内存。


//调用ClassA的析构函数


//调用ClassA的基类RefBase的析构函数,需要注意的是,此步骤并没有执行

//delete mRef动作,只是简单地将mRef赋为NULL(即影子对象的生命还是完好存

//在的,内存尚未被回收)


//返回到pARefBase::decStrong(constvoid* id),继续执行:refs->decWeak(id);


//影子对象被删除,内存空间至此才被回收。


Sample2:创建一个ClassA的对象(ClassA继承自RefBase),并传给模板类wp(weak pointer, 弱指针) ,通过在win32下的debug分解其运行过程:

1)执行模板类wp的构造函数:template<typenameT> wp<T>::wp(T* other);

// 直接run,开始debug


// 增加弱引用计数的值,并将获取到的影子对象的指针存储至m_refs


// 注意此函数返回的是影子对象


//


2)执行模板类wp的析构函数:template<typenameT> wp<T>::~wp(T* other);

// 模板类wp的对象wpA的生命期即将结束


//


// 删除ClassA的对象pA


//


// 删除pA的影子对象,释放内存


【结论】

         从sample1知道,当使用强指针引用一个对象时,强引用计数和弱引用计数都会增加1,强指针变量销毁时,通过析构函数的调用过程分析,二者均减1。

         从sampl2知道,当使用弱指针引用一个对象时,只有弱引用计数会增减1,强引用计数值不受影响。

(七)使用方法

1)关于sp的使用例子1:

//


2)关于sp的使用例子2

//


//


3)关于wp的使用例子:

//


//


//


(八)总结

         今天周六,闲来无聊,一时心血来潮,就将Android中的智能指针porting至win32下run了一把。不敢私藏,就将一些心得贡献出来。希望此文能够帮助刚接触Android或者希望了解Android智能指针的朋友:掌握了wp和sp,学习起Android各个native端模块才会得心应手!

         本文的运行环境:将android sp/wp相关code porting至win32下,使用visual studio 2010进行debug。希望取得win32 project在vc上run的朋友,可以向我索取source code project。

          【注:本文是基于Android 4.0.3的source code进行的分析】【2013/8/9】


参考文献:

<<深入剖析Android系统>>     杨长刚

http://blog.csdn.net/innost/article/details/6752443







原创粉丝点击