反汇编分析NSString,你印象中的NSString是这样吗
我们先来定义三个NSString
-(void) testNSString
{
NSString* a = @"abc";
NSString* b = [NSString stringWithUTF8String:"abc"];
NSString* c = [@"ab" stringByAppendingString:@"c"];
}
大家都明白,a, b, c 都equalsToString:@"abc"。但是它们是指向同一个对象实例呢,还是根本就不是同一种类型。我们来看一下反汇编代码:
function_args`-[ViewController testNSString]:
0x10bd48590 <+>: pushq %rbp
0x10bd48591 <+>: movq %rsp, %rbp
0x10bd48594 <+>: subq $0x40, %rsp
0x10bd48598 <+>: leaq 0x1ac9(%rip), %rax ; @"abc"
0x10bd4859f <+>: movq %rdi, -0x8(%rbp) ; // save %rdi
0x10bd485a3 <+>: movq %rsi, -0x10(%rbp) ; // save %rsi
0x10bd485a7 <+>: movq %rax, %rdi
0x10bd485aa <+>: callq 0x10bd48b1c ; symbol stub for: objc_retain
0x10bd485af <+>: leaq 0x616(%rip), %rdx ; "abc"
0x10bd485b6 <+>: movq %rax, -0x18(%rbp) ; // NSString* a
-> 0x10bd485ba <+>: movq 0x277f(%rip), %rax ; (void *)0x000000010c05db20: NSString // (Class)$rax = NSString
0x10bd485c1 <+>: movq 0x2730(%rip), %rsi ; "stringWithUTF8String:"
0x10bd485c8 <+>: movq %rax, %rdi
0x10bd485cb <+>: callq 0x10bd48b0a ; symbol stub for: objc_msgSend
0x10bd485d0 <+>: movq %rax, %rdi
0x10bd485d3 <+>: callq 0x10bd48b28 ; symbol stub for: objc_retainAutoreleasedReturnValue
0x10bd485d8 <+>: leaq 0x1aa9(%rip), %rdx ; @"ab"
0x10bd485df <+>: leaq 0x1ac2(%rip), %rsi ; @"'c'"
0x10bd485e6 <+>: movq %rax, -0x20(%rbp) ; // NSString* b
0x10bd485ea <+>: movq 0x270f(%rip), %rax ; "stringByAppendingString:"
0x10bd485f1 <+>: movq %rdx, %rdi ; // lea 0x1aa9(<+79>) -> %rdx -> %rdi
0x10bd485f4 <+>: movq %rsi, -0x40(%rbp)
0x10bd485f8 <+>: movq %rax, %rsi ; // lea 0x270f(<+97>) -> %rax -> %rsi
0x10bd485fb <+>: movq -0x40(%rbp), %rdx ; // 0x1ac2(<+86>) -> %rsi -> -0x40(%rbp) -> %rdx
0x10bd485ff <+>: callq 0x10bd48b0a ; symbol stub for: objc_msgSend
0x10bd48604 <+>: movq %rax, %rdi
0x10bd48607 <+>: callq 0x10bd48b28 ; symbol stub for: objc_retainAutoreleasedReturnValue
0x10bd4860c <+>: movq %rax, -0x28(%rbp) ; // NSString* c
0x10bd48610 <+>: movq -0x18(%rbp), %rax
0x10bd48614 <+>: movq %rax, %rdi
0x10bd48617 <+>: callq 0x10bd48b22 ; symbol stub for: objc_retainAutorelease
NSString* a = @"abc"; 的反汇编片段如下:
0x10bd48598 <+>: leaq 0x1ac9(%rip), %rax ; @"abc"
0x10bd4859f <+>: movq %rdi, -0x8(%rbp) ; // save %rdi
0x10bd485a3 <+>: movq %rsi, -0x10(%rbp) ; // save %rsi
0x10bd485a7 <+>: movq %rax, %rdi
0x10bd485aa <+>: callq 0x10bd48b1c ; symbol stub for: objc_retain
0x10bd485b6 <+>: movq %rax, -0x18(%rbp) ; // NSString* a
如大家所知,@"abc"是一个全局实例,并且对其retain了一次(,因为是ARC环境),然后由a指向了它。
剩下的b和c却是从stringXXX调用中返回的,到底返回了什么,在没有调试过之前,你我都不好一口定金说它返回的就是什么。好就由调试器lldb告诉我们。
0x7fff53eb59a8: 0x00007fce7b706230 // NSString* c {retainCount:, hash:} (__NSCFString *)
0x7fff53eb59b0: 0xa000000006362613 // NSString* b {retainCount:-, hash:} (NSTaggedPointerString *)
0x7fff53eb59b8: 0x000000010bd4a068 // NSString* a {retainCount:-, hash:} (__NSCFConstantString *)
你断言对了吗?lldb给我们的信息真不少,真是可靠的小伙伴。
首先三者指向的目标不一样。
第二retainCount唯独c是可数的,表明它们生命周期不同。
第三它们的hash一致,表明它们的内容一样。
最后真真切切打印,它们不同类,是同宗。
我们先分析指针,第一列绿字地址,表明a,b,c是在堆栈中指针变量,而且地址相邻,和我的定义代码一致。然后看第二列地址,是a,b,c分别指向的地址,c指向堆栈下向某处,没错那就是堆;而b是一个无理头地址,看过我上一篇的介绍就会知道这是一个tagged指针;至于a中规中矩说出它就是全局实例。
原来a,b,c都不是同一样实例。但是结论可能定得太早。
现在我们再来分析它们的生命周期,它们的生命周期受谁掌控。c毫无疑问是受retain/release控制的。然而a,b岂不在retain的时候就被dealloc? 通过反汇编跟踪b@tagged指针忽略retain/release,a@__NSCFConstantString的retain/release不做任何处理。表明了a,b是与程序一样长寿的寿星公。那么这两位寿星公的关系几何呢,它们有上一腿吗?你会怀疑它们是同一身份吗?
不要净是我在说,如果你还不知道真相的话,也有兴趣弄明白就请阁下亲自验证一下了。
最后我们看一下lldb给出的NSString的类的父子链
NSString
NSMutableString
__NSCFString
__NSCFConstantString
NSString
NSTaggedPointerString
另外要清楚一点,objc中的继承是接口继承,不一定是成员继承,大家都知道声明都用@interface,class是可以动态构造的。
最后,又一次多谢大家的观看,更多的objc分析请关注后面的文章。
下一篇大家将会看到幽灵一样的指针TaggedPointer。
反汇编分析NSString,你印象中的NSString是这样吗的更多相关文章
- 九、Foundation框架中的NSString常用方法
一.NSString的创建 方式1创建常量字符串 NSString *st = @"this is string!"; //这种方式创建的字符串不需要释放 方式2创建空字符串,给予 ...
- (转载)OC学习篇之---Foundation框架中的NSString对象和NSMutableString对象
在之前的一篇文章中我们说到了Foundation框架中的NSObject对象,那么今天在在来继续看一下Foundation框架中的常用对象:NSString和NSMutableString. 在OC中 ...
- OC学习篇之---Foundation框架中的NSString对象和NSMutableString对象
今天在在来继续看一下Foundation框架中的常用对象:NSString和NSMutableString 在OC中NSString对象是不可变的,和Java中的String一样的,而NSMutabl ...
- objc反汇编分析,block函数块为何物?
上一篇向大家介绍了__block变量的反汇编和它的伪代码,本篇函数块block,通常定义成原型(^){},它在反汇编中是什么东西. 我们先定义将要反汇编的例子,为减少篇幅例子采用non-arc环境. ...
- Linux下简单C语言小程序的反汇编分析
韩洋原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 写在开始,本文为因为参加MOO ...
- 反汇编分析objc函数枢纽objc_msgSend
在分析objc_msgSend之前,先来搞清楚另一个问题. 函数是什么?可能会答 void foo(void) {} 像这样就是一个函数.或者函数包括函数原型和函数定义,是一段执行某样功能的机器代码. ...
- Hbase源码分析:Hbase UI中Requests Per Second的具体含义
Hbase源码分析:Hbase UI中Requests Per Second的具体含义 让运维加监控,被问到Requests Per Second(见下图)的具体含义是什么?我一时竟回答不上来,虽然大 ...
- 深度分析如何在Hadoop中控制Map的数量
深度分析如何在Hadoop中控制Map的数量 guibin.beijing@gmail.com 很多文档中描述,Mapper的数量在默认情况下不可直接控制干预,因为Mapper的数量由输入的大小和个数 ...
- 零元学Expression Blend 4 - Chapter 7 什麽?影片不再是印象中的方框框!!!看Blend 4如何把影片镶入字里
原文:零元学Expression Blend 4 - Chapter 7 什麽?影片不再是印象中的方框框!!!看Blend 4如何把影片镶入字里 本章将教大家如何在Blend 4里新增Media El ...
随机推荐
- std::tuple
tuple,元组类型.头文件<tuple>,tuple是一个固定大小的不同类型(异质,heterogeneous)值的集合(这一点是tuple与其他常规STL容器的最大不同,即它可以同时存 ...
- AB实验的高端玩法系列2 - 更敏感的AB实验, CUPED!
背景 AB实验可谓是互联网公司进行产品迭代增加用户粘性的大杀器.但人们对AB实验的应用往往只停留在开实验算P值,然后let it go...let it go ... 让我们把AB实验的结果简单的拆解 ...
- 百万年薪python之路 -- 并发编程之 多线程 三
1. 阻塞,非阻塞,同步,异步 进程运行的三个状态: 运行,就绪,阻塞. 从执行的角度: 阻塞: 进程运行时,遇到IO了,进程挂起,CPU被切走. 非阻塞: 进程没有遇到IO 当进程遇到IO, ...
- 【Java】遍历List/Set/Map集合的一些常用方法
/* * 遍历List/Set/Map集合的一些常用方法 */import java.util.ArrayList;import java.util.HashMap;import java.util. ...
- 使用maven替换项目依赖中的字节码
问题描述 我们偶尔会发现一些开源项目的问题,或者出于其他原因,想在某个dependency的代码中加几行或者删除几行来达到目的. 我这里遇到一个dubbo 2.7.3和open feign冲突的问题 ...
- (六)添加adbmingling
给环境变量Path添加adb命令路径,即adb.exe所在的目录 C:\Users\LIU Liang\AppData\Local\Android\Sdk\platform-tools
- jquery链式原理.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- SpringCloud之Feign和Ribbon的选择(五)
Ribbon Ribbon 是一个基于 HTTP 和 TCP 客户端的负载均衡器它可以在客户端配置 ribbonServerList(服务端列表),然后轮询请求以实现均衡负载它在联合 Eureka 使 ...
- DRF之认证组件、权限组件、频率组件使用方法总结
认证组件格式: from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions ...
- 几种部署Goku API Gateway的方式,最快一分钟可使用上网关
本文将介绍几种部署Goku API Gateway的方式,最快一分钟可使用上为网关,详情请看全文. 什么是Goku API Gateway? Goku API Gateway (中文名:悟空 API ...