以前问过大光一个问题 nsstring类型的对象的值存在哪里了呢?是否和person类一样有个属性name来存储"jasikar"呢?或像大光回答的p5指针指向的既是"jasikar"? 答案是否定的。搜索nsstring的帖子大多写了nsstring指向的是常量内存区,没有更具体的说明了。那今天碰巧想到了个问题解决方法。
先写结论:nsstring *p5 指向的是个对象,地址0x100002098 对象中只有一个isa_t 的isa指针(这里isa_t是一个union,被解析成不同成员,一个对象在没有属性的情况下最少占用16个字节,其中8个字节是isa指针,另外的8个字节是额外信息(还需查资料,自己不太清楚)
x/8xw 0x100002098 0x100002098: 0x9e1181d8 0x00007fff 0x000007c8 0x00000000
0x1000020a8: 0x00001dce 0x00000001 0x00000007 0x00000000
结论是jasikar 的指针存储在对象地址+0x10的地方0x1000020a8:0x00001dce 0x00000001
intmain(intargc,constchar* argv[]) {
@autoreleasepool {
NSString*p5 =@"jasikar";
constchar* a =[p5 UTF8String];
NSLog(@"a对应的字符串对应的字符常量区地址= %p",p5);
在Xcode中建立NSString *p5 = @"jasikar",通过追踪p5 的 UTF8String方法实现来解析nsstring 对象
(lldb) p ( char *)0x0000000100001dce
(char *) $1022 = 0x0000000100001dce "jasikar"
(lldb) p (objc_object * )0x100002098
(objc_object *) $1023 = 0x0000000100002098
(lldb) p *$1023
(objc_object) $1024 = {
isa = 0x00007fff9e1181d8
}
(lldb) p (objc_class *)0x00007fff9e1181d8
(objc_class *) $1025 = 0x00007fff9e1181d8
(lldb) p *$1025
(objc_class) $1026 = {
objc_object = {
isa = 0x001dffff9e118189
}
superclass = __NSCFString
cache = {
_buckets = 0x0000000100f59f10
_mask = 7
_occupied = 6
}
bits = (bits = 4310790448)
}
(lldb) p $1025.data()
(class_rw_t *) $1027 = 0x0000000100f17130
Fix-it applied, fixed expression was:
$1025->data()
(lldb) p *$1027
(class_rw_t) $1028 = {
flags = 2148007936
version = 0
ro = 0x00007fff9e0faea0
methods = {
list_array_tt = {
= {
list = 0x00007fff9e0fadd8
arrayAndFlag = 140735845215704
}
}
}
properties = {
list_array_tt = {
= {
list = 0x00007fff9e0fae88
arrayAndFlag = 140735845215880
}
}
}
protocols = {
list_array_tt = {
= {
list = 0x00007fff9e0fad78
arrayAndFlag = 140735845215608
}
}
}
firstSubclass = nil
nextSiblingClass = nil
demangledName = 0x0000000000000000
}
(lldb) p $1027.ro
(const class_ro_t *) $1029 = 0x00007fff9e0faea0
Fix-it applied, fixed expression was:
$1027->ro
(lldb) p *$1029
(const class_ro_t) $1030 = {
flags = 16
instanceStart = 8
instanceSize = 8
reserved = 0
ivarLayout = 0x0000000000000000
name = 0x00007fff434a28e9 "__NSCFConstantString"
baseMethodList = 0x00007fff9e0fadd8
baseProtocols = 0x00007fff9e0fad78
ivars = 0x0000000000000000
weakIvarLayout = 0x0000000000000000
baseProperties = 0x00007fff9e0fae88
}
这里是__NSCFConstantString类的内容。怎么也找不到"jasikar"在哪里。
设断点进入 UTF8String内部 这里是CoreFoundation 全是汇编写的。
跳过CFstringMtbl,进入CFStringGetCstringPtr函数,这是关键。
一点一点分析,传入的%rdi =0x10002098 %rsi =8000100 是上图贴的转换类型,实现的关键在下面这个代码
0x7fff4307b8a0<+116>: movq 0x8(%r14), %rax //r14=0x10002098 rax =0x7c8
0x7fff4307b8a4<+120>: testb $0x8, %al. //
0x7fff4307b8a6 <+122>: je 0x7fff4307b9a0 ; <+372>//不跳
0x7fff4307b8ac<+128>: movq 0x8(%r14), %rcx //rcx =0x7c8
0x7fff4307b8b0<+132>: leaq 0x10(%r14), %rax. //rax =0x1000020a8
0x7fff4307b8b4<+136>: testb $0x60, %cl
0x7fff4307b8b7 <+139>: je 0x7fff4307b949 ; <+285>
0x7fff4307b8bd<+145>: movq (%rax), %rcx. // rcx=0x100001dce
//这里能看到 rax是 对象1000020a8 +0x10 即是对象地址处+16个字节处存储了"jasikar"
0x7fff4307b8c0 <+148>: jmp 0x7fff4307b95d ; <+305>
0x7fff4307b95d<+305>: movq 0x8(%r14), %rax
0x7fff4307b961<+309>: shrl $0x2, %eax
-> 0x7fff4307b964<+312>: andl $0x1, %eax
0x7fff4307b967<+315>: addq %rcx, %rax
0x7fff4307b96a <+318>: jmp 0x7fff4307b9a2 ; <+374>
0x7fff4307b9a2 <+374>: popq %rbx
0x7fff4307b9a3<+375>: popq %r14
0x7fff4307b9a5<+377>: popq %rbp
0x7fff4307b9a6 <+378>: retq
到这里就结束了 可以看到rax unsigned long 0x0000000100001dce,最返回的是"jasikar"所在地址。 本文到此结束了。结论是jasikar 的指针存储在对象地址+0x10的地方。。