反汇编分析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 ...
随机推荐
- go-异常处理-error-panic-recover
Go语言的函数可以一次返回多个结果.这就为我们温和地报告错误提供了语言级别的支持. func readFile(path string) ([]byte, error) { file, err := ...
- i春秋DMZ大型靶场实验(三)内网转发DMZ2
更具实验文件知道存在源码泄露 下载源码进行源码审计 发现admin账号 查看user.php 发现mysql 账号 端口 对登录后源码进行审计 发现上传文件的两处漏洞 对 fiel name 可以 ...
- javascript函数前面加~波浪线的作用
如下,在函数前加上波浪号,其作用是把函数声明转换为表达式,这样就可以直接运行. ~function sayHello(){ console.log('hello'); }() 测试: 在console ...
- Charles抓包工具的使用(一)
前提:charles的说明 Charles其实是一款代理服务器,通过过将自己设置成系统(电脑或者浏览器)的网络访问代理服务器,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在W ...
- 课堂动手动脑验证以及自定义异常类实现对异常处理——java异常类
异常(exception):发生在程序执行期间,表明出现了一个非法运行的情况.许多JDK中的方法在检测到非法情况时,都会抛出一个异常对象.例如:数组越界和被0除. 代码验证: package test ...
- Java基础(二十)集合(2)Collection接口
1.Collection接口通常不被直接使用.但是Collection接口定义了一些通用的方法,通过这些方法可以实现对集合的基本操作,因为List接口和Set接口都实现了Collection接口,所以 ...
- jquery引用
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- POJ2431 优先队列+贪心 - biaobiao88
以下代码可对结构体数组中的元素进行排序,也差不多算是一个小小的模板了吧 #include<iostream> #include<algorithm> using namespa ...
- char 、signed char、unsigned char
看如下代码: char c = -1; signed char sc = -1; unsigned char uc = -1; printf("c=%d, sc=%d, uc=%d, cx= ...
- Java开发中的23中设计模式详解(一)工厂方法模式和抽象工厂模式
一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...