以前問過大光一個(gè)問題 nsstring類型的對(duì)象的值存在哪里了呢殴蓬?是否和person類一樣有個(gè)屬性name來存儲(chǔ)"jasikar"呢匿级?或像大光回答的p5指針指向的既是"jasikar"? 答案是否定的。搜索nsstring的帖子大多寫了nsstring指向的是常量內(nèi)存區(qū)根蟹,沒有更具體的說明了脓杉。那今天碰巧想到了個(gè)問題解決方法。
先寫結(jié)論:nsstring *p5 指向的是個(gè)對(duì)象简逮,地址0x100002098?對(duì)象中只有一個(gè)isa_t ?的isa指針(這里isa_t是一個(gè)union球散,被解析成不同成員,一個(gè)對(duì)象在沒有屬性的情況下最少占用16個(gè)字節(jié)散庶,其中8個(gè)字節(jié)是isa指針蕉堰,另外的8個(gè)字節(jié)是額外信息(還需查資料,自己不太清楚)
x/8xw?0x100002098 ? ?0x100002098: 0x9e1181d8 0x00007fff 0x000007c8 0x00000000
0x1000020a8: 0x00001dce 0x00000001 0x00000007 0x00000000
結(jié)論是jasikar 的指針存儲(chǔ)在對(duì)象地址+0x10的地方0x1000020a8:0x00001dce 0x00000001
intmain(intargc,constchar* argv[]) {
? ? @autoreleasepool {
? ? ? ? NSString*p5 =@"jasikar";
? ? ? ? constchar* a =[p5 UTF8String];
? ? ? ? NSLog(@"a對(duì)應(yīng)的字符串對(duì)應(yīng)的字符常量區(qū)地址= %p",p5);
在Xcode中建立NSString *p5 = @"jasikar"悲龟,通過追蹤p5 的?UTF8String方法實(shí)現(xiàn)來解析nsstring 對(duì)象
(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類的內(nèi)容屋讶。怎么也找不到"jasikar"在哪里。
設(shè)斷點(diǎn)進(jìn)入?UTF8String內(nèi)部 這里是CoreFoundation 全是匯編寫的须教。
跳過CFstringMtbl皿渗,進(jìn)入CFStringGetCstringPtr函數(shù),這是關(guān)鍵轻腺。
一點(diǎn)一點(diǎn)分析乐疆,傳入的%rdi =0x10002098 %rsi =8000100 是上圖貼的轉(zhuǎn)換類型,實(shí)現(xiàn)的關(guān)鍵在下面這個(gè)代碼
? ?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是 對(duì)象1000020a8 +0x10 即是對(duì)象地址處+16個(gè)字節(jié)處存儲(chǔ)了"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? ?
到這里就結(jié)束了 可以看到rax unsigned long 0x0000000100001dce贬养,最返回的是"jasikar"所在地址挤土。 本文到此結(jié)束了。結(jié)論是jasikar 的指針存儲(chǔ)在對(duì)象地址+0x10的地方误算。仰美。