sp&wp 的三板斧

anroid智能指针(wp,sp)学习总结 智能指针sp和wp在android c++源码中使用非常频繁,例如IBinder机制,但是它比c++中普通的智能指针要复杂很多,相信不少android学习者如果c++基础不是很扎实的,看起来会比较吃力和枯燥。本人在android 4.2.2源码基础上对sp和wp的关键代码做了详细解析,着重分析原理,相信您看了该文档,一定会有所收获,一定对sp和wp有新的认识。 立即下载

根据《深入理解Android 卷I》改编而来、加入自已的理解而来。对于sp&wp的理解一直知道不够深入、真好有时间、彻底深究一下、典型的程序员风格。透过代码看本质。这里对于最核心的sp&wp的构造及析构讲解。


参考代码下载地址:

http://download.youkuaiyun.com/detail/andyhuabing/9254171 通过eclipse打开c工程、即可单步调试。


第一个板斧例子:

//类A从RefBase派生,RefBase是万物的始祖
class A: public RefBase {
	//A没有任何自己的功能
};

static void example1() {
	printf("test example1 \n");
	A* pA = new A();
	{
		//注意我们的sp,wp对象是在{}中创建的,下面的代码先创建sp,然后创建wp
		sp<A> spA(pA);
		wp<A> wpA(spA);
		//大括号结束前,先析构wp,再析构sp
	}
	printf("test example1 finish!\n");
}

1、构造对象

A* pA = new A(); 构造一个Refbase对象

RefBase::RefBase()

    : mRefs(new weakref_impl(this))

{

}

此处再构造一个weakref_impl对象、称为 影子对象、后续也主要是利用影响对象进行计数据加减


weakref_impl(RefBase* base)

        : mStrong(INITIAL_STRONG_VALUE)

        , mWeak(0)

        , mBase(base)

        , mFlags(0)

    {

    }


这里初始化 mStrong=INITIAL_STRONG_VALUE  (1<<28)、mWeak=0、且将实际对象即A存储在mBase中


小结一下:

构造RefBase对象、同时构造了weakref_impl影子对象、并将影子对象的强引用mStrong及mWeak赋初始值。


2、sp上场:

 sp<A> spA(pA);


模块构造

template<typename T>

sp<T>::sp(T* other)

: m_ptr(other)

  {

    if (other) other->incStrong(this);

  }


m_ptr 保存了 pA 的指针、并调用pA的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);
	printf("incStrong c=0x%x \n", c);
	if (c != INITIAL_STRONG_VALUE) {
		return;
	}
	android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
	printf("decStrong mStrong=0x%x \n", refs->mStrong);
	refs->mBase->onFirstRef();
}

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);
	printf("incWeak c=0x%x, mWeak=0x%x \n", c, impl->mWeak);
}


此时先执行
在 RefBase::incStrong 中 先执行weakref_type::incWeak、再执行refs->mStrong的计数、通过打印如下:


通过打印看到
incWeak c=0x0, mWeak=0x1 
incStrong c=0x10000000 
incStrong mStrong=0x1 
call onFirstRef 

弱引用计数加1、强引用计数加1 、第一次调用refs->mBase->onFirstRef(); 用于完成初始化工作。


3、wp 构造

wp<A> wpA(spA);


template<typename T>
wp<T>::wp(const sp<T>& other)
    : m_ptr(other.m_ptr)
{
    if (m_ptr) {
        m_refs = m_ptr->createWeak(this);
    }
}

此时 m_ptr 指定实际对象 spA 、并调用 createWeak()函数

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


通过打印看到
incWeak c=0x1, mWeak=0x2 

即影子对象的弱引用计数为2、强引用计数为1


4、wp 对象析构


调用析构函数:

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

调用 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);
	printf("decWeak c=0x%x, mWeak=0x%x \n", c, impl->mWeak);
	if (c != 1)
		return;

	printf("decWeak mFlags =0x%x \n", impl->mFlags);
	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.
		printf("decWeak mStrong=0x%x \n", impl->mStrong);
		if (impl->mStrong == INITIAL_STRONG_VALUE) {
			// Special case: we never had a strong reference, so we need to
			// destroy the object now.
			printf("decWeak object now11 \n");
			delete impl->mBase;
		} else {
			printf("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.
			printf("decWeak object now22 \n");
			delete impl->mBase;
		}
	}
}

通过打印:

decWeak mWeak=0x2 
decWeak c=0x2, mWeak=0x1 


c值为2则直接返回、此时强弱引用计数都为1 


5、sp 对象析构

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

调用 decStrong后结果:

decStrong mStrong=0x1 
decStrong c=0x1 
decStrong mFlags=0 
decStrong delete self object 


此时将调用 delete this 即调用:

RefBase::~RefBase() {
	printf("call RefBase::~RefBase mRefs->mFlags=0x%x \n", mRefs->mFlags);
	printf("call RefBase::~RefBase mStrong=0x%x \n", mRefs->mStrong);
	printf("call RefBase::~RefBase mWeak=0x%x \n", mRefs->mWeak);
	if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
		// we never acquired a strong (and/or weak) reference on this object.
		delete mRefs;
	} else {
		// life-time of this object is extended to WEAK or FOREVER, in
		// which case weakref_impl doesn't out-live the object and we
		// can free it now.
		if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
			// It's possible that the weak count is not 0 if the object
			// re-acquired a weak reference in its destructor
			if (mRefs->mWeak == 0) {
				delete mRefs;
			}
		}
	}
	// for debugging purposes, clear this.
	const_cast<weakref_impl*&> (mRefs) = NULL;
}


打印如下:

call RefBase::~RefBase mRefs->mFlags=0x0 
call RefBase::~RefBase mStrong=0x0 
call RefBase::~RefBase mWeak=0x1 


由于  mWeak 为1 导致影响对象依然存在。继续执行 RefBase::weakref_type::decWeak 函数:


decWeak mWeak=0x1 
decWeak c=0x1, mWeak=0x0 
decWeak mFlags =0x0 
decWeak mStrong=0x0 
Freeing refs 0xada330 of old RefBase 0xada320

实际对象值:

example1 pA=0xcba320

example1 spA=0xcba320 
example1 wpA=0xcba330 


小结:

1、Refbase 有一个隐含的影子对象、该影子对象内部有强弱引用计数

2、sp化后、强弱引用计数各增加1、sp析构后、强弱引用计数各减1

3、wp化后、弱引用计数增加1、wp析构后、弱引用引数减1 

当 flags参数为0时、有如下结论:

1、强引用计数为0时则将实际对象 delete 释放

2、弱引用计数为0时则将影子对象 delete 释放


对于flags参数:

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

可以以此为点继续分析再不再续了,比较简单。



保姆级教程:在DolphinScheduler 3.x中配置Apache SeaTunnel任务(Flink/Spark双引擎) 本文提供了一份详细的教程,指导如何在DolphinScheduler 3.x中配置Apache SeaTunnel任务,支持Flink和Spark双引擎。从环境准备、脚本选择到配置文件编写和任务调度优化,涵盖了所有关键步骤和常见问题解决方案,帮助用户高效集成SeaTunnel到海豚调度系统中。 阅读详情

相关推荐

保姆级教程:Unity编辑器汉化全流程(从下载到配置避坑指南)

本文提供Unity编辑器汉化的保姆级教程,涵盖从下载中文语言包到配置避坑的全流程。详细解析版本适配、文件系统交互及编辑器底层配置逻辑,帮助开发者高效完成汉化,解决常见报错问题,提升工作效率。

weixin_30825581的博客 155

Android系统篇之----Android中的智能指针

一、前言 今天我们开启Android系统篇的文章了,其实一直想弄,只是之前一直没有太多深入的了解,最近又把这块拿出来好好看了一下,所以想从新梳理一下,来看看Android中的这块知识,首先我们今天来看一下:Android中的智能指针的概念,为什么说先看一下智能指针这个知识呢?因为我们在看Android源码的时候,会发现几乎好多地方都用到了这个东东,所以我们在介绍后面的知识点,先来看看这个吧。

qq_34856433的博客 744

CAD的.dwg文件导入 ArcGIS:高程分析、坡度分析、坡向分析

CAD的.dwg文件导入 ArcGIS,再进行高程分析、坡度分析、坡向分析。

My_Echo_yM的博客 7238

Android智能指针分析(sp、wp)

在Android native编写代码时,会经常接触到sp、wp,sp并不是smart pointer

lilian0118的专栏 1万+

SpringBoot+Maven打包实战:把项目变成SDK供其他团队调用

本文详细介绍了如何将SpringBoot项目改造并打包成可被其他项目依赖的SDK。通过调整Maven配置,剥离SpringBoot父依赖与启动类,并定制打包插件,最终生成标准的JAR依赖库,实现从“可执行应用”到“组件化SDK”的优雅转变,便于团队间功能复用。

assembly8low的博客 827

有限状态机FSM详解(一)

有限状态机在维基百科中的解释是: 有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。 至于为什么要学FSM,FSM可以把模型的多状态、多状态间的转换条件解耦。可以使维护变得容易,代码也更加具有可读性,也更加艺术。 理解有限状态机首先需要理解整个模型。我们把灯的开关作为示例,...

benjonc的博客 5万+

Android 智能指针详解 -- RefBase

源码基于:Android N 相关博文:Android 智能指针详解Android 智能指针详解 -- wp Android 智能指针详解 -- spAndroid 智能指针详解 -- RefBase 关于android 智能指针,前面详细分析了sp 和 wp的source code,但是还有一些疑问,在这一篇中全部解释,因为所有的源头都是来自于这里。更多信息可以看 sp的博文 和 wp的博文source code:system/core/include/utils/RefBase.hsystem/core

私房菜 1万+

打造会自主学习的 AI 助手:OpenClaw 记忆系统完全指南

这不是科幻,这是我正在使用的系统。我的 AI 助手「小琳」已经运行了一段时间,积累了大量的知识和经验,而且还在不断学习成长。心跳(Heartbeat)是 OpenClaw 的定时轮询机制,可以让 AI 主动做一些事情。你有没有遇到过这样的困扰:每次和 AI 对话,它都像失忆了一样,之前聊过的内容完全不记得?设置定时任务:每天早上 8 点,查询天气和热点新闻,通过钉钉推送给我。让你的 AI 助手拥有持久记忆,能够自主学习、总结经验、不断成长。这不仅仅是一个「能记住事情的 AI」,而是一个。

Honmaple的博客 1633

Cubietruck---13.sp与wp分析_深入理解android第五章笔记

Cubietruck---13.sp与wp分析_深入理解android第五章笔记

wangcong02345的专栏 495

虚拟化 之三 详解 ARM 平台 jailhouse 的移植适配、构建及使用(飞腾派)

本文将探索学习通过在飞腾官方提供的 Buildroot 构建系统移植适配 openEuler 内核以及 jailhouse 源码 Package 进而直接构建一个适用于飞腾派开发板的带有 jailhouse 的 openEuler 发行版。

技术干货 1004

【软考高级架构】论文范文12——论生成式AI在软件开发中的应用与挑战

随着生成式AI技术的跨越式发展,以大语言模型为代表的生成式AI正在深刻改变软件开发的传统模式。在代码生成、测试构造、文档编写等环节,生成式AI展现出显著的效率提升潜力,但其应用也面临着代码质量不可控、安全漏洞植入、版权合规等严峻挑战。本文以笔者主导的某大型金融企业智能研发辅助平台建设项目为案例,围绕生成式AI在软件开发中的应用实践与应对挑战的策略展开论述。笔者担任系统架构师,负责平台架构设计、模型选型、质量保障机制及安全防线构建。

qq837993702的博客 275

Android C++回收机制(转)

1关于C++ Layer的内存回收机制 Android C++层的内存收回主要是通过三个类来实现,分别是RefBase,sp,wp; SP和WP是两个智能指针模板类,sp是strong pointer,wp则是weak pointer,亦我们常说的强引用和弱引用;实例化sp和wp这两个模板类的类型必须是派生自RefBase的类1.1 RefBase类 因为这个类拥有对内存回收机制的...

weixin_30315435的博客 188

大数据在电力行业的应用案例解析 -【电力技术】(十)电力数字化运营与大数据精准服务体系建设

电力数字化运营,是大数据在电力行业从技术场景走向业务价值的最终落点。它以数据为纽带,将用户、设备、服务、收益、风险全部纳入统一闭环,实现从 “管好电” 向 “运营好能源资产” 升级。在新型电力系统与市场化改革双重驱动下,谁能用好数据、建好闭环、做好运营,谁就能在服务、成本、效益、安全上建立长期优势。

getusushu的博客 69

深入浅出 - Android系统移植与平台开发(十三)- Android的对象管理

第六章、Android的对象管理在Java中,不再使用的对象会通过gc机制来自动回收,而Android系统运行时库层代码是由C++编写的,在C++中创建的对象通常使用指针来操作,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃。不过在Android源码实现中,它为我们提供了智能指针来对C++对象进行管理,这使得程序员不再需要关注对象的生命周期、对象是否已经释放。本章主要内容如下:l 智能指针l R

mr_raptor的专栏 7828

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

android智能指针sp wp详解

<br />研究android的时候,经常会遇到sp、wp的东西,网上一搜,原来是android封装了c++中对象回收机制。<br />说明:<br />1. 如果一个类想使用智能指针,那么必须满足下面两个条件:<br />    a. 该类是虚基类RefBase的子类或间接子类<br />    b. 该类必须定义虚构造函数。如virtual ~MyClass();<br />2. 本文以类BBinder来进行说明,其余类使用sp或wp的情况类似<br />3. 代码路径:frameworks/base/

zgolee的专栏 7705

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Android的垃圾回收机制(android refbase类(sp wp))

android sp wp

765

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

sp<> 强指针类的用法

文一: 转:http://wangjun-1985.spaces.live.com/blog/cns!E9070276AAF56C8E!472.entry 在android 中可以广泛看到的template class Sp 句柄类实际上是android 为实现垃圾回收机制的智能指针。智能指针是c++ 中的一个概念,因为c++ 本身不具备垃圾回收机制,而且指针也不具备构造函数和析构函数,所以为

lksodit_yiyi的专栏 1万+

android中的智能指针

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34074740的博客 457

Android 强弱引用

Android 强弱引用 软件:Source Insight 4.0、starUml 代码目录: system/core/include/utils/RefBase.h system/core/include/utils/StrongPointer.h system/core/libutils/RefBase.cpp 一、简介 从media服务的main函数入口中,可以发现 sp<P...

小熊猫的地盘 858

android sp和wp

android sp和wp android的sp是指strong pointer wp则是weak pointer,引入他们的目的是解决C++中容易出现的空指针、野指针、new 和 delete导致的内存泄漏或者访问出错问题。   无论时sp还是wp,其目标对象都需要继承refBase类,改为为其子类提供了引用计数变量mstrong 、mweak以及用于对变量进行操作的operation 函...

kuang_tian_you的博客 2253

Android -- sp、wp智能指针的原理简介

Android -- sp、wp强弱指针的原理简介 我们知道,Android的native层代码基本都是C/C++的天下;基于这种特点,在native层中大量使用指针来操作对象就在所难免了。由于C/C++需要程序员手动操作管理内存,这就使程序出现内存管理问题的概率大大特高。所以,在Android中就提出了一种新的指针概念:强指针(sp)、弱指针(wp)来代替普通的指针;这种指针基于引用计

To be or not to be, it's a question 7251

[转]Android中的sp和wp指针

经常会在android的framework代码中发现sp&amp;amp;amp;amp;amp;lt;xxx&amp;amp;amp;amp;amp;gt;和wp&amp;amp;amp;amp;amp;lt;xxx&amp;amp;amp;amp;amp;gt;这样的指针,平时看的时候都把他当成一个普通的指针封装过掉了,这几天终于忍不住了,想深入了解一下。 相关的代码: frameworks/base/include/utils/RefBase.h frameworks

爱技术的蓝胖子 794

[Android] 智能指针sp与wp

智能指针sp与wp 在AOSP中,Google实现了一套特有的智能指针系统,用来方便C++工程中的内存管理。内存释放是C++工程中非常难处理的一部分,为此一些C++工程都会有自己的智能指针系统,C++11的std中也提供了auto_ptr之类的智能指针的概念。 从auto_ptr说起 我们先看下C++ 11中的auto_ptr,这个比AOSP中的较容易理解。 auto_ptr在memory.h中,...

博客已搬家,请访问新博客https://kswapd.cn,提供更好的阅读体验。 2029

[深入理解Android卷一全文-第五章]深入理解常见类

由于《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知识的传播不应该因为纸质媒介的问题而中断,所以我将在优快云博客中全文转发这两本书的全部内容。第5章 深入理解常见类本章主要内容·  分析RefBase、sp,wp和LightRefBase类。·  分析Native的Thread类和常用同步类。·  分析Java层的Handler、Looper,以及HandlerTh

Innost的专栏 8690

android 绘指针,Android智能指针

“Yeah It’s on. ”前言在Android系统中,Native层的代码基本都是C++写的,C++跟Java不一样,C++没有垃圾回收机制,C++代码中难于管理new出来对象的释放,稍有不慎就造成内存泄漏。针对此问题,Android中提出了一套类似Java垃圾回收机制的智能指针,采用强指针sp(Strong Pointer)和弱指针wp(Weak Pointer)对目标对象进行应用,实现对...

weixin_35817545的博客 474

Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析

Android系统的运行时库层代码是用C++来编写的,用C++来写代码最容易出错的地方就是指针了,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃。不过系统为我们提供了智能指针,避免出现上述问题,本文将系统地分析Android系统智能指针(轻量级指针、强指针和弱指针)的实现原理。 在使用C++来编写代码的过程中,指针使用不当造成内存泄漏一般就是因为new了一个对象并且使用完之...

oraclestudy 925
上一篇: Android 无法接收开机广播的问题
下一篇: 读 <<富爸爸财务自由之路>> 之感
andyhuabing
博客等级 码龄19年 704粉丝 165原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值