刚开始实习,进入公司所干的事儿虽然和以前没有太大区别,都是看代码调试代码,但是这是与以前所看过的代码都不一样,需要补充相关的基础理论知识,需要静下心来,慢慢学习和补充。
以下是未来几天需要学习的内容:
一、Android 源码中智能指针的分析
在Android 底层运行库层源码中,经常会碰到sp<T>,wp<T>这样的代码,这是Google编写的针对C++指针释放的一种机制,有点类似于JAVA或者C#中垃圾回收机制,当某个对象没有被别人引用后,系统会自动回收。C++一般使用delete回收资源,为什么要使用这种所谓的智能指针呢?原因有二:一是很多程序猿编写C++代码时,忘记释放new出来的对象,或者不知道什么时候该释放这个对象;二是对象已经释放,在其他地方再次引用,造成指针异常;
程序猿在编写程序的时候需要精心设计程序,以避免上面两种问题,例如需要书写很多代码来检查输入的对象是不是已经释放掉了,在释放资源的时候还得考虑是不是其他地方还用到这个对象的引用。在引入智能指针概念以后,这种问题就变得很简单了,程序猿不用担心自己的new出来的对象没有释放而造成内存泄露,也不用担心引用已经释放的对象的引用,这样大大提高了程序的编写效率,同时也提高了系统的稳定性。
说了这么多废话,Google是如何实现所谓的智能指针的呢?
关于智能指针的定义和实现在这两个文件中:
frameworks\base\include\utils\RefBase.h
frameworks\base\libs\utils\RefBase.cpp
关于如何实现就不那么详细的说了!这里仅仅说说实现原理。智能指针通过引用计数来实现智能的,即每个对象在new的时候都会有一个计数值,来记录这个对象被引用的次数,被引用一次,这个计数值加一,当不再使用这个引用时,这个计数值就减一,当计数值减到一的时候,表示这个对象没有被引用了,可以自动销毁了。但是在实际应用中,不会直接孤立的定义一个新的变量来记录一个对象的引用次数,而是将新指针与这个计数值整合到一块,这样还有一个问题就是每次引用的时候主动调用加一,不用的时候调用减一,还是无法解决忘记加一或者忘记减一的问题,问题又回到了原点。在android中,引用计数功能就放在Refbase这个类中,这个类来实现计数的统计,以及对象的销毁,而引用计数何时加减问题,是通过另外一个类sp(Strong Pointer)来实现,通过这个类的构造和析构来实现引用计数的加减,这样就解决了计数的加减问题。如果仅仅使用单一的引用计数无法解决循环引用的问题,比如对象A引用了对象B,而在对象B中又引用了对象A,那么当对象A和B就无法被自动销毁,因为当系统发现A该销毁时,发现A还被B(B从哪里来呀?A中引用B)中引用着,这样系统就无法回收A,同样的道理,也无法回收A,这样就会出现内存泄露的问题了。但是办法总是比问题多,有问题就有解决问题的办法,使用两种计数值:强引用计数和弱引用计数,当父对象引用子对象时就对子对象使用强引用计数,当子对象引用父对象时,就对父对象采用弱引用计数,当强对象引用计数为零,就不管弱对象引用计数是否为零,就强制收回资源,当一个对象只有弱引用计数时,如果要使用这个对象,就要把这个对象提升为强引用计数才可以使用。
这样说还是非常抽象,看看如何使用以后就知道上面的意思。
class RefBase {//这个类是很sp的基类,里面有引用计数的管理的相关实现 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); bool attemptIncStrong(const void* id); //! This is only safe if you have set OBJECT_LIFETIME_FOREVER. 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); } protected: RefBase(); virtual ~RefBase(); //! Flags for extendObjectLifetime() enum { OBJECT_LIFETIME_WEAK = 0x0001, OBJECT_LIFETIME_FOREVER = 0x0003 }; 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 weakref_type; class weakref_impl; RefBase(const RefBase& o); RefBase& operator=(const RefBase& o); weakref_impl* const mRefs; };对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); }下面看看如何使用智能指针以及该注意的问题: