亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁(yè) > 系統(tǒng) > iOS > 正文

一道值得深入思考的iOS面試題詳解

2019-10-21 18:22:00
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

最近在群里看到有人發(fā)的一道面試題,題目如下:

@interface Spark : NSObject @property(nonatomic,copy) NSString *name; @end@implementation Spark- (void)speak { NSLog(@"My name is:%@",self.name); }@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad];  id cls = [Spark class];  void *obj = &cls;  [(__bridge id)obj speak];}

問(wèn)題:上述代碼運(yùn)行起來(lái)會(huì):Complie error?|Runtime crash?|NSLog ?

最終問(wèn)題就是這段代碼的運(yùn)行結(jié)果。

過(guò)程

第一眼看這個(gè)問(wèn)題,我直接就想說(shuō),這個(gè)東西啊,肯定是編譯報(bào)錯(cuò)了、要不就是崩潰啊

所以我就跟著寫了些代碼,結(jié)果發(fā)現(xiàn):

WTF? 怎么能運(yùn)行,而且結(jié)果竟然還是

iOS,面試題

相信當(dāng)你看到這個(gè)結(jié)果的時(shí)候會(huì)和我一樣吃驚,不和邏輯啊,怎么竟然能執(zhí)行成功并且還打印出來(lái)當(dāng)前controller了,不符合常理啊。

解析

對(duì)于計(jì)算機(jī)而言,不存在什么魔法,如果一段代碼能運(yùn)行必然存在它的原理。

我們需要做的就是分析為什么能成功。

為什么調(diào)用不崩潰

我們需要了解,cls的意思。

cls在C語(yǔ)言里,就是一個(gè)指針,這個(gè)指針的內(nèi)容指向Spark類

當(dāng)我們通過(guò)void *obj = &cls;這個(gè)語(yǔ)句執(zhí)行后,獲取的就是一個(gè)指向這個(gè)指針cls的指針

事實(shí)上在這一步操作實(shí)現(xiàn)后,obj 這個(gè)指針就已經(jīng)具有Object-c對(duì)象的功能了,為什么呢?接下來(lái)我們可以看看runtime實(shí)現(xiàn)原理了,這里我只說(shuō)一點(diǎn)

//對(duì)象struct objc_object { Class isa OBJC_ISA_AVAILABILITY;};//類 struct objc_class { Class isa OBJC_ISA_AVAILABILITY;#if !__OBJC2__ Class super_class     OBJC2_UNAVAILABLE; const char *name      OBJC2_UNAVAILABLE; long version      OBJC2_UNAVAILABLE; long info      OBJC2_UNAVAILABLE; long instance_size     OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars    OBJC2_UNAVAILABLE; struct objc_method_list **methodLists   OBJC2_UNAVAILABLE; struct objc_cache *cache     OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols   OBJC2_UNAVAILABLE;#endif} OBJC2_UNAVAILABLE;//方法列表struct objc_method_list { struct objc_method_list *obsolete   OBJC2_UNAVAILABLE; int method_count      OBJC2_UNAVAILABLE;#ifdef __LP64__ int space      OBJC2_UNAVAILABLE;#endif /* variable length structure */ struct objc_method method_list[1]   OBJC2_UNAVAILABLE;}        OBJC2_UNAVAILABLE;//方法struct objc_method { SEL method_name      OBJC2_UNAVAILABLE; char *method_types     OBJC2_UNAVAILABLE; IMP method_imp      OBJC2_UNAVAILABLE;}

 

上述簡(jiǎn)介中部分是錯(cuò)誤的,因?yàn)檫@個(gè)只是在<objc/runtime.h>中的顯示,但是覺得直接刪除又顯現(xiàn)不出更改。因而在此專門寫出,我會(huì)在下面給出正確的解釋與數(shù)據(jù)來(lái)源

struct objc_class : objc_object { // Class ISA; Class superclass; cache_t cache;  // formerly cache pointer and vtable class_data_bits_t bits;}

數(shù)據(jù)來(lái)源: 蘋果obj4開源代碼 第1012行 用以替換 上述簡(jiǎn)述引用中的 objc_class

可以看到objc_object這個(gè)對(duì)象的首字段是isa 指向一個(gè)Class

也就是說(shuō),我們?nèi)绻幸粋€(gè)指向Class的地址的指針,相當(dāng)于這個(gè)對(duì)象就已經(jīng)可以使用了,只是像他的成員變量等等的一系列值都還沒有被初始化。

所以接下來(lái)用(__bridge id)obj,調(diào)用是不會(huì)產(chǎn)生問(wèn)題的

為什么能打印出ViewController對(duì)象?

這個(gè)問(wèn)題就是由兩個(gè)小部分組成的

1.  name 這個(gè)屬性是什么時(shí)候賦的值?

2.  ViewController 這個(gè)對(duì)象是什么時(shí)候被傳入的?

首先我們需要先了解一下,一個(gè)類對(duì)象的數(shù)據(jù)是如何存儲(chǔ)的。

這里我就按照上文一樣引用很多的論證了,我們自己來(lái)探究

該上代碼了:

@interface Cls : NSObject @property(nonatomic,strong) NSString *test; @property(nonatomic,strong) NSString *test1;@end@implementation Cls- (void)printPrinter { NSLog(@"self:%p",self); NSLog(@"self.test:%p",&_test); NSLog(@"self.test1:%p",&_test1);}@end

接下來(lái)調(diào)用printPrinter,打印一下對(duì)象指針地址:

iOS,面試題

可以發(fā)現(xiàn),指針偏移量成員變量和指針首地址差8個(gè)字節(jié),每個(gè)成員變量與上一個(gè)成員變量偏移量也是8個(gè)字節(jié)。

完成到這一步,我們?nèi)匀粵]有發(fā)現(xiàn)上述兩個(gè)問(wèn)題是應(yīng)該怎么解釋。但是我們知道了,一個(gè)Object-C 對(duì)象的指針,和它的成員變量的指針肯定是連續(xù)的。這就為接下來(lái)我們的分析提供了一些思路。

下一步,我在原本的題目中增加一行代碼:

[super viewDidLoad];NSString *str = @"11111"; id cls = [Spark class];

為啥要增加這行代碼呢,這步是經(jīng)過(guò)深(瞎)思(J)熟(B)慮(試),主要是考慮到函數(shù)內(nèi)部的參數(shù)生成必然會(huì)需要地方存儲(chǔ),但這部分存儲(chǔ)地址,我們是不知曉的,它的實(shí)現(xiàn)是被系統(tǒng)隱藏的。而我們的代碼又沒有明顯的設(shè)置相關(guān)代碼,那么必然是由這些條件實(shí)現(xiàn)的。所以當(dāng)我們?cè)黾恿诉@一行代碼后,不出意外的,打印結(jié)果變了

2018-11-29 20:49:39.254021+0800 test[1961:92498] My name is:11111

變成了 我們 上述的值,這一切都和猜想的差不多

于是一個(gè)基本設(shè)想就出來(lái)了:

因?yàn)闂I系牡刂方Y(jié)構(gòu)和原本類的需求地址結(jié)構(gòu)高度重合了,同時(shí)所有地址都能訪問(wèn)到對(duì)應(yīng)的值。我們通過(guò)棧的默認(rèn)行為生成了一個(gè)Spark對(duì)象!

為了驗(yàn)證,我們打印一下cls和str的指針堆棧地址

NSLog(@"cls address:%p str address:%p",&cls,&str);

2018-11-29 21:03:30.490989+0800 test[2129:122769] cls address:0x7ffeebf4fa00 str address:0x7ffeebf4fa08

我們可以看到他們之間相差也正好是8,而且正好和對(duì)象結(jié)構(gòu)體定義的一模一樣。所以這也正好能說(shuō)明我們上述的打印結(jié)果My name is:11111為什么會(huì)發(fā)生。

注:這個(gè)存在的原因是因?yàn)楹瘮?shù)內(nèi)部變量采用的小端模式,也就是將參數(shù)地址由棧區(qū)從高地址依次向低地址分配,所以我們打印cls地址會(huì)比str要小。

由此,第一個(gè)小問(wèn)題就解決了,答案是因?yàn)槲覀冊(cè)谏啥褩?shù)的時(shí)候,拼湊出了Spark對(duì)象的地址數(shù)據(jù)結(jié)構(gòu)格式,和真正的對(duì)象地址數(shù)據(jù)結(jié)構(gòu)一樣,所以self.name就是在生成cls的那一刻起內(nèi)存地址就已經(jīng)被賦值了。

接下來(lái)到下一個(gè)問(wèn)題了ViewController 是什么時(shí)候傳入的?

在這一步里我們只能把目光向cls對(duì)象生成前執(zhí)行的操作來(lái)看,[super viewDidLoad];我們只執(zhí)行了這一步操作,那必然是這個(gè)操作產(chǎn)生的結(jié)果。為了驗(yàn)證,我們可以更改一下調(diào)用順序

id cls = [Cls class]; [super viewDidLoad];

當(dāng)我們進(jìn)行這部操作后,會(huì)發(fā)現(xiàn),執(zhí)行speak方法時(shí)崩潰了,錯(cuò)誤是EXC_BAC_ACCESS,說(shuō)明是我們引用野指針了。
由此也可以證實(shí),[super viewDidLoad];肯定做了一些騷操作,將ViewController的self壓入了棧區(qū)。

接下來(lái)我們就需要探究究竟做了什么操作,我們可以用如下的命令行代碼將ViewController.m重寫成c++代碼,然后觀看發(fā)生了什么。

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc ViewController.m -o ViewController.cpp
static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) { ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad"));

我們可以發(fā)現(xiàn)原本這個(gè)方法里面會(huì)傳入兩個(gè)參數(shù)一個(gè)是self,一個(gè)是_cmd,當(dāng)我們調(diào)用[super viewDidLoad]時(shí),執(zhí)行的方法中傳入了參數(shù)self,由此將self做為一個(gè)值壓入了棧中,但是_cmd這個(gè)參數(shù)并未被使用,因此,沒有被壓入棧中。

至此,這個(gè)問(wèn)題已經(jīng)被解釋出來(lái)了。

答案

所有NSObject對(duì)象的首地址都是指向這個(gè)對(duì)象的所屬類。這個(gè)條件是充要條件。反過(guò)來(lái)說(shuō),如果一個(gè)地址指向某個(gè)類,我們就可以把這個(gè)地址當(dāng)成對(duì)象去用。所以編譯是會(huì)通過(guò)的,也不會(huì)報(bào)unrecognized selector的錯(cuò)誤。

打印結(jié)果會(huì)是ViewController對(duì)象的原因是因?yàn)閏ls在棧上的數(shù)據(jù)結(jié)構(gòu)符合了它作為真實(shí)的類時(shí)候的數(shù)據(jù)結(jié)構(gòu),cls.name原本地址正好是棧上ViewController對(duì)象地址,因此NSLog能打印出<ViewController >

思索

這類問(wèn)題,考察的東西很深,并且結(jié)合了很多知識(shí)點(diǎn)。但是當(dāng)我們拿到面試題并且能進(jìn)行思索的時(shí)候一定要好好的考慮,我對(duì)這道題的想法,也是在不斷的試驗(yàn)中逐漸的完善,并且嘗試了很多。其實(shí)找面試題為什么是這個(gè)答案的過(guò)程和,找代碼找bug的流程都是類似的,都是排除變量,逐步探索,最終將探索過(guò)程和概念結(jié)合。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到IOS開發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产欧美日韩不卡免费| 久久精品国产屋| 日韩免费网站| 精品人伦一区二区色婷婷| 日韩国产精品久久| 视频一区视频二区中文字幕| 最全影音av资源中文字幕在线| 亚洲一本二本| 国产精品小说在线| 亚洲精品一区二区毛豆| 欧美 日韩 人妻 高清 中文| 一个色在线综合| 婷婷色在线资源| 成片免费观看视频| 乱中年女人av三区中文字幕| 日韩亚洲第一页| 国产精品一国产精品| 欧美日韩视频免费在线观看| 加勒比在线一区二区三区观看| 欧美wwwww| 99国产在线观看| 乱人伦视频在线| 99精品全国免费观看视频软件| av黄色免费在线观看| 黄色毛片在线观看| 99免在线观看免费视频高清| 久久av秘一区二区三区| 成人短视频软件网站大全app| 国产自产2019最新不卡| 久久99伊人| 国产成人午夜精品| 成人精品小蝌蚪| 国产成人一区二区三区别| 亚洲天堂网一区| 亚洲第一狼人社区| 99免费观看视频| 超碰97在线资源站| 黄色片视频网站| www.狠狠爱| 亚洲第一页在线视频| 久久综合九色综合97_久久久| 成人三级高清视频在线看| 久久精品一区二区三区不卡| 中文字幕日韩视频| 久久久久久91精品色婷婷| 精品久久久久久久久久久院品网| 国产精品18毛片一区二区| 久久久国产精品成人免费| 超碰超碰超碰超碰超碰| 久久久精品五月天| 免费在线观看国产精品| 国产精品久久中文字幕| 国产精品99久久久久久似苏梦涵| 懂色av一区二区三区免费看| 一本久久a久久精品vr综合| 91无套直看片红桃在线观看| 国产三级在线免费| 狠狠色综合色综合网络| 孩娇小videos精品| 成人午夜影视| 欧美视频精品| 男人的天堂在线视频免费观看| 国产午夜在线一区二区三区| 国产系列在线观看| 丁香花免费高清完整在线播放| 亚洲成人www| 一级久久久久久| 无码人妻精品一区二区三区99v| 亚洲尤物在线视频| 在线视频观看一区二区| 欧美成人禁片在线www| 97香蕉超级碰碰久久免费的优势| 亚洲性图久久| 99国产精品99久久久久久粉嫩| 91最新国产视频| 国产精品7m视频| 久久久九九九九| 亚洲区精品久久一区二区三区| 图片区乱熟图片区亚洲| 一区二区三区在线播放欧美| 欧美wwwxxxx| 欧美激情视频免费观看| 6699嫩草久久久精品影院| 99视频精品免费观看| 久久99久久99精品免观看粉嫩| 久久久国产精品午夜一区ai换脸| 日本福利片在线| 911精品美国片911久久久| 亚洲一区中文在线| av无码精品一区二区三区| 欧美日韩ab| 99久久国产免费看| 国产suv精品一区二区三区88区| 国产精品视频无码| 亚洲成年人视频| 九色porny蝌蚪视频在线观看| 一个人在线观看免费视频www| 亚洲品质自拍视频网站| 亚洲视频网在线直播| 国产精品九九久久久久久久| 亚洲精品欧洲| wwww在线观看免费视频| www.youjizz.com在线| 中文字幕资源站| 色综合天天做天天爱| 色av成人天堂桃色av| 精品久久久久久久久久岛国gif| 一卡二卡三卡亚洲| 精品国产成人av在线免| 日韩理论在线| 成人18夜夜网深夜福利网| 日韩专区中文字幕| 久久久久久免费网| 天堂网站www天堂资源在线| 日本不卡在线视频| 日本中文字幕电影| 国产91精品一区二区绿帽| 久草视频免费播放| 国产成人精品免费网站| 久久精品91久久久久久再现| 少妇高潮一区二区三区喷水| 中文字幕在线中文| 亚洲欧美在线人成swag| 国产99视频精品免费视频36| 91丨九色丨丰满| 一女三黑人理论片在线| 国产一区二区中文| 在线播放免费| 精品人妻无码一区二区三区| 亚洲欧美中文日韩v在线观看| 精品久久97| 亚洲精品偷拍视频| 亚洲免费一级视频| 国产综合在线观看| 成人资源av| 91麻豆福利| aaaaaaaa毛片| 国产欧美精品一区二区三区四区| 天天干天天插天天操| 做爰高潮hd色即是空| 久久夜色精品国产欧美乱| 欧美日韩国产一中文字不卡| 99久久久久免费精品国产| 国产精品久久波多野结衣| 91精品国产综合久久精品app| 亚洲综合激情小说| av资源中文色综合| 国产又粗又猛又爽又黄视频| 欧美日韩国产精品自在自线| 香蕉视频污视频| 在线永久免费观看黄网站| 综合久久久久久久| 国产不卡精品视男人的天堂| 午夜在线视频播放| 妺妺窝人体色www在线小说| 免费人成在线观看播放视频| 亚洲视频欧洲视频| 欧美激情xxxx| 99精品在线观看视频| 精品美女www爽爽爽视频| 欧美久久一级| 东京热无码av男人的天堂| 男人的天堂狠狠干| 国产婷婷成人久久av免费高清| 欧美一区二区三区在线| 仙踪林久久久久久久999| 亚洲日本va| 国产精品99蜜臀久久不卡二区| 久久亚洲精品成人| 亚洲欧美国产高清va在线播| 岛国一区二区在线观看| 久久久爽爽爽美女图片| 2020欧美日韩在线视频| 在线观看黄色| 超级白嫩亚洲国产第一| 中文字幕亚洲一区| 欧美精品www| 国产精品视频福利| 一本大道色婷婷在线| 日韩电影一区二区三区四区| 亚洲图片小说网| 狠狠88综合久久久久综合网| 视色视频在线观看| 成年人二级毛片| 国产精品久久久久高潮| 在线精品高清中文字幕| 国产专区一区二区三区| 亚洲mv大片欧洲mv大片| 精品一区二区三区久久久| 欧美国产日韩a欧美在线观看| 先锋影音久久久| 精品久久久久久亚洲国产300| 中文字幕免费在线看线人动作大片| 免费观看黄一级视频| 亚洲一区二区三区黄色| 国产精品日韩一区二区免费视频| 久久久精品福利| 91电影在线播放| 久久精品夜夜夜夜久久| 亚洲成人黄色小说| 91蝌蚪在线| 三上悠亚一区| 欧美尤物一区| 99thz桃花论族在线播放| 无限国产资源| 中文字幕日韩高清在线| 久久久久久欧美精品色一二三四| 久热中文字幕精品视频在线| 国产精品国产三级国产aⅴ原创| yjizz视频| 九色91蝌蚪| 久久精品第一页| 亚洲小说欧美激情另类| japanese色系久久精品| 亚洲开发第一视频在线播放| 国产麻豆精品一区二区三区v视界| 91久久精品国产91久久| 91高清视频| 色午夜这里只有精品| 欧美日韩大片免费观看| 色哺乳xxxxhd奶水米仓惠香| 成人污网站在线观看| 午夜精品久久久久久不卡8050| 日本三区在线观看| 黑人巨大亚洲一区二区久| h文在线观看免费| 日韩欧美一区二区三区视频| 国产在视频线精品视频| 成人午夜精品无码区| 综合在线一区| 一区免费视频| 一级香蕉视频在线观看| 国产又色又爽又黄又免费| 成人在线免费观看网站| 日本黄色的视频| 日韩有码在线播放| 日韩免费高清在线观看| 日本大胆在线观看| 亚洲免费大片在线观看| 色菇凉天天综合网| 久久久久久久久久久久久91| 免费成人在线视频网站| free性欧洲69| 九九热在线观看视频| 综合激情在线| 秋霞欧美视频| 二区三区偷拍浴室洗澡视频| 亚洲少妇激情视频| 性视频在线播放| 亚洲国产精品自拍| 欧美国产精品| 久久久国产一区二区| 97国产一区二区| 曰本三级日本三级日本三级| 在线播放日韩欧美| 日韩精品成人一区二区在线观看| 色婷婷av久久久久久久| 成人免费视频免费观看| 国产又粗又长又爽又黄的视频| 久久久噜噜噜久久人人看| 视频一区二区三区在线看免费看| 四虎精品影院在线观看视频| 欧美日韩黄色大片| 最新日韩三级| 国产精品婷婷午夜在线观看| 日韩在线免费播放| 91传媒理伦片在线观看| 国产精品qvod| 欧美在线导航| 欧美午夜不卡在线观看免费| 国产精品免费观看| 男人女人黄一级| 麻豆av在线免费看| 蜜臀久久精品久久久用户群体| 久久综合99re88久久爱| 国产蜜臀一区二区打屁股调教| 韩国v欧美v日本v亚洲v| 亚洲日本一区二区| 成人三级av在线| 成人免费毛片在线观看| 欧美大交乱xxxx| 午夜在线网站| 7777久久亚洲中文字幕| 91freevideo| 欧美中文一区| 在线能看的黄色| 亚洲一区在线观看免费观看电影高清| av中文字幕免费在线观看| 国产三级短视频| 久久激情一区| 国产精品黄色大片| 日韩欧美亚洲天堂| 国产最新在线| 久久九九热免费视频| 欧美三级午夜理伦三级富婆| 日本免费一区二区三区四区| 成人久久一区| 91香蕉国产在线观看软件| 国产又粗又猛又爽又黄的视频小说| 嫩草视频免费在线观看| 国产精品嫩草影视| 国产xxxxx视频| 中文字幕人妻熟女人妻洋洋| 日韩黄色免费观看| 五十路亲子中出在线观看| 国产区在线观看视频| 中文在线最新版地址| 色哟哟精品视频| 成人午夜在线观看| a视频在线免费看| 91丝袜美腿美女视频网站| 欧美三级午夜理伦三级| 尤物在线免费视频| 蜜桃av在线| 亚洲欧洲成人在线| 91精品婷婷色在线观看| 国产精品.com| 成人免费看片98| 日本女人高潮视频| 亚洲sss视频在线视频| 中文字幕视频在线| 国产乱人乱偷精品视频| 亚洲黄页视频免费观看| 在线看片黄色| 欧美另类老肥妇| china中国猛gary| 日本中文字幕在线视频观看| 国产精品嫩草影院久久久|