Android 上C++对象的自动回收机制分析
来源:互联网 发布:talkback是什么软件 编辑:程序博客网 时间:2024/05/01 15:55
1. 背景
C++没有像Java那样的内建的对象自动回收机制,new创建的对象没有delete,会一直存在于内存中。对象已经不再使用,但是如果忘记 delete,会造成内存资源的泄露。在实际开发过程中,分析内存泄露是一件很棘手的事情。本文基于Android2.2系统源码,对Android的 C++对象自动回收机制进行分析。
2. 引用计数和智能指针
Android上C++对象实现自动释放的机制是使用引用计数+智能指针。对象的生命周期通过引用计数来管理,当引用计数>0时,对象不会被释放;当引用计数=0时,释放该对象。
使用对象的方式是通过智能指针引用该对象,智能指针也是C++对象,利用C++的构造析构自动调用的特性,在构造函数中将对象的引用计数加1,析构函数中减1,当计数减为0时delete该对象,这样通过智能指针+引用计数就实现了对象的自动化管理。
下面通过代码分析具体实现过程。
3. RefBase
Android中C++类一般都会直接或间接继承RefBase类,RefBase类有一个成员变量mRefs,mRefs是 weakref_impl类型,weakref_impl记录着引用计数、目标对象(通过引用计数管理的对象)指针和符号位。通过继承RefBase,使 类具有引用计数的功能。
1
weakref_impl*
const
mRefs;
1
class
RefBase::weakref_impl :
public
RefBase::weakref_type
2
{
3
public
:
4
volatile
int32_t mStrong;
// 强引用计数
5
volatile
int32_t mWeak;
// 弱引用计数
6
RefBase*
const
mBase;
// 目标对象
7
volatile
int32_t mFlags;
// 标志位,初始是OBJECT_LIFETIME_STRONG
8
…
9
};
1
RefBase::RefBase()
2
3
: mRefs(
new
weakref_impl(
this
))
4
5
{};
4. 强引用计数和弱引用计数
在讨论智能指针前我们先考虑这样一种情况。假设A对象是由MA模块来创建和销毁的,MB模块的B对象增加A对象的引用计数来使用A对象,有一种情况 是:MA模块比MB模块提前被销毁,由于B对象使用着A,A的引用计数不为0,则A不会被销毁。在MA销毁后B继续使用A,假设A使用了MA模块的其他对 象或者资源,这时就会出问题,因为MA模块的其他对象或者资源已经销毁了。
为了解决上述问题,引用计数细分为强引用计数和弱引用计数。一般情况下,强引用计数控制着对象生命周期,如果强引用计数减为0时目标对象自动析构,即使弱引用计数不为0。弱引用计数后面介绍。
5. sp和wp
前面说过,智能指针管理着对象的引用计数,Android中智能指针的实现是sp和wp。sp是strong pointer,wp是weak pointer。sp增加引用计数会分别将强引用计数和弱引用计数+1,wp增加引用计数时只会讲弱引用计数+1,。因此,弱引用计数总是 >= 强引用计数。sp可以保证目标对象一直是有效的,但wp不能保证,因此wp不能直接调用目标对象的方法,wp需要提升为sp后才能调用目标对象的方法。所 以wp没有提供指针操作符重载方法(operator* ()和operator->)。
sp和wp分别定义在
frameworks/base/include/utils/StrongPointer.h和frameworks/base/include/utils/RefBase.h文件。
sp对象构造调用incStrong
01
template
<
typename
T>
02
03
sp<T>::sp(T* other)
04
05
: m_ptr(other)
06
07
{
08
09
if
(other) other->incStrong(
this
);
10
11
}
01
void
RefBase::incStrong(
const
void
* id)
const
02
{
03
weakref_impl*
const
refs = mRefs;
04
refs->incWeak(id);
// mWeak += 1
05
const
int32_t c = android_atomic_inc(&refs->mStrong);
// mStrong += 1
06
…
07
if
(c != INITIAL_STRONG_VALUE) {
08
return
;
09
}
10
…
11
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
12
}
1
template
<
typename
T>
2
sp<T>::~sp()
3
{
4
if
(m_ptr) m_ptr->decStrong(
this
);
5
}
01
void
RefBase::decStrong(
const
void
* id)
const
02
{
03
…
04
const
int32_t c = android_atomic_dec(&refs->mStrong);
// mStrong += 1
05
…
06
if
(c == 1) {
07
…
08
if
((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
09
delete
this
;
10
}
11
}
12
refs->decWeak(id);
// mWeak -= 1
13
}
wp对象的构造和析构过程也是类似的,构造时mWeak加1,析构时mWeak减1
6. wp提升为sp的过程
wp对象调用promote方法返回sp对象,如果sp指向的对象已经销毁,promote返回NULL
1
template
<
typename
T>
2
sp<T> wp<T>::promote()
const
3
{
4
sp<T> result;
5
if
(m_ptr && m_refs->attemptIncStrong(&result)) {
6
result.set_pointer(m_ptr);
7
}
8
return
result;
9
}
可以将wp提升为sp的三种情况:
1、 没有sp指向目标对象且mStrong == INITIAL_STRONG_VALUE
2、 没有sp指向目标对象且mStrong == 0 且mFlags == OBJECT_LIFETIME_WEAK
3、有sp指向目标对象
attemptIncStrong()代码说明了上面的三种情况
01
bool
RefBase::weakref_type::attemptIncStrong(
const
void
* id)
02
03
{
04
05
incWeak(id);
06
07
weakref_impl*
const
impl =
static_cast
<weakref_impl*>(
this
);
08
09
int32_t curCount = impl->mStrong;
10
11
LOG_ASSERT(curCount >= 0,
"attemptIncStrong called on %p after underflow"
,
12
13
this
);
14
15
while
(curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
16
17
if
(android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
18
19
break
;
20
21
}
22
23
curCount = impl->mStrong;
24
25
}
26
27
if
(curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
28
29
bool
allow;
30
31
if
(curCount == INITIAL_STRONG_VALUE) {
32
33
// Attempting to acquire first strong reference... this is allowed
34
35
// if the object does NOT have a longer lifetime (meaning the
36
37
// implementation doesn't need to see this), or if the implementation
38
39
// allows it to happen.
40
41
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
42
43
|| impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
44
45
}
else
{
46
47
// Attempting to revive the object... this is allowed
48
49
// if the object DOES have a longer lifetime (so we can safely
50
51
// call the object with only a weak ref) and the implementation
52
53
// allows it to happen.
54
55
allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
56
57
&& impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
58
}
59
if
(!allow) {
60
decWeak(id);
61
return
false
;
62
}
63
64
curCount = android_atomic_inc(&impl->mStrong);
65
…
66
67
}
68
}
69
impl->addStrongRef(id);
70
71
…
72
73
return
true
;
74
75
}
7. weakref_impl对象标志位的作用
当mFlags 为OBJECT_LIFETIME_STRONG 时,强引用计数为0时,销毁对象
当mFlags为OBJECT_LIFETIME_WEAK时,强引用计数为0时,不销毁对象,弱引用减为0时,才销毁对象,由于弱引用计数 >= 强引用计数,所以OBJECT_LIFETIME_WEAK延长了对象的存在时间,下面的代码说明了这种情况。当mWeak == 0 且 mFlags == OBJECT_LIFETIME_WEAK时,释放目标对象。
01
void
RefBase::weakref_type::decWeak(
const
void
* id)
02
{
03
const
int32_t c = android_atomic_dec(&impl->mWeak);
04
if
(c != 1)
return
;
05
if
((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
06
…
07
}
else
{
08
// less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
09
impl->mBase->onLastWeakRef(id);
10
if
((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
11
// this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
12
// is gone, we can destroy the object.
13
delete
impl->mBase;
14
}
15
}
16
}
8. 其他特性
RefBase提供了以下四个重载方法,子类可以继承实现,以便跟踪引用计数的变化情况。
1
// 当mStrong从INITIAL_STRONG_VALUE更改为1时,该方法被调用
2
virtual
void
onFirstRef();
3
// 当mStrong从减为0时,该方法被调用
4
virtual
void
onLastStrongRef(
const
void
* id);
5
// 控制是否允许将wp提升为sp,返回true表示允许
6
virtual
bool
onIncStrongAttempted(uint32_t flags,
const
void
* id)
7
// 当mWeak减为0时且mFlags == OBJECT_LIFETIME_WEAK,该方法被调用
8
virtual
void
onLastWeakRef(
const
void
* id);
9. 总结
RefBase为C++对象提供了引用计数,sp和wp通过管理引用计数,达到自动控制目标对象生存期的目的。
- Android 上C++对象的自动回收机制分析
- Android上C++对象的自动回收机制分析
- Android上C++对象的自动回收机制分析
- Android上C++对象的自动回收机制分析
- 垃圾回收机制(对象的回收)
- java对象的回收机制
- 关于java的自动回收机制
- java 数据库连接的自动回收机制 removeAbandoned
- Android的垃圾回收机制
- Android的垃圾回收机制
- Android的垃圾回收机制
- Android的进程回收机制
- Android的垃圾回收机制
- Android的进程回收机制
- Android的进程回收机制
- 对象的回收机制深度剖析
- 对象的销毁与垃圾回收机制
- 全面分析Java的垃圾回收机制
- linux内核从2.4.20升级到2.6.18 2010-03-30 22:18:50
- 1111111
- CSDN班级选拔试题
- Linux LCD驱动(三)--图形显示
- GIS专有词汇
- Android 上C++对象的自动回收机制分析
- 雷锋网2011年度10大iPhone游戏
- 适配器模式(adapter)
- 在SQL Server里查看当前连接的在线用户数
- SQL 左外连接,右外连接,全连接,内连接
- hibernate15道精选面试题
- C# 中的委托和事件
- 用OpenXml SDK 2.0 创建一个页脚带页码的Word文档
- svn import