Android智能指针浅析(win32 debug)
来源:互联网 发布:淘宝怎么看评价几星 编辑:程序博客网 时间:2024/05/16 11:48
============= 目录结构:===========
(一)引言
(二)摘录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:
protected: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;
//! 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
//调用pA的RefBase::incStrong()函数,强引用计数值和引用计数值分别+1
3)执行模板类sp的析构函数: template<typenameT> sp<T>::~sp();
// 模板类sp的对象spA的生命期即将结束
//调用模板类sp的析构函数
//调用pA的RefBase::decStrong(constvoid* id),删除ClassA的对象pA,释放内存。
//调用ClassA的析构函数
//调用ClassA的基类RefBase的析构函数,需要注意的是,此步骤并没有执行
//delete mRef动作,只是简单地将mRef赋为NULL(即影子对象的生命还是完好存
//在的,内存尚未被回收)。
//返回到pA的RefBase::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
- Android智能指针浅析(win32 debug)
- Android智能指针浅析
- 浅析智能指针(一)
- 浅析:智能指针
- C++智能指针浅析
- 浅析c++智能指针
- 浅析C++智能指针
- 【C++】 浅析智能指针
- 浅析智能指针一
- 浅析智能指针二
- 浅析智能指针
- 浅析智能指针
- 智能指针浅析
- Android 智能指针(1)
- 浅析C++中的智能指针
- c++之浅析智能指针
- Android智能指针分析(sp、wp)
- Android智能指针分析(sp、wp)
- SPOJ 362. Ignore the Garbage 规律+大数除法
- Longest Substring Without Repeating Characters
- Codeforces Round #195 (Div. 2) A Vasily the Bear and Triangle
- JSF、Richfaces学习
- 安卓4.0 中如何在app 中屏蔽HOME键
- Android智能指针浅析(win32 debug)
- RHEL 6.1 可以下载了
- Android有关Home按键的TYPE_KEYGUARD作用
- JAVA获取文件编码
- 大学,是什么呢?
- Android中的Environment.getExternalStorageState使用
- 【32位+64位】msvcr100.dll
- 报表属性下的各个选项的使用
- CGRectInset的使用