iOS | 面試 - 內存管理

iOS | 面試知識整理 - 內存管理(五)

1.什么是內存泄漏?

內存泄漏指動態分配內存的對象在使用完后沒有被系統回收內存,導致對象始終占有著內存,屬于內存管理出錯, (例如一個對象或者變量使用完成后沒有釋放,這個對象一直占用著內存),一次內存泄露危害可以忽略,但內存泄露堆積后果很嚴重,無論多少內存,遲早會被占光。

2. 什么是僵尸對象?

已經被銷毀的對象(不能再使用的對象),內存已經被回收的對象。一個引用計數器為0對象被釋放后就變為了僵尸對象;

3. 野指針

野指針又叫做'懸掛指針', 野指針出現的原因是因為指針沒有賦值,或者指針指向的對象已經釋放了, 比如指向僵尸對象;野指針可能會指向一塊垃圾內存,給野指針發送消息會導致程序崩潰

比如:

NSObject*obj = [NSObjectnew];[obj release];// obj 指向的內存地址已經釋放了,obj 如果再去訪問的話就是野指針錯誤了.野指針錯誤形式在Xcode中通常表現為:Thread1:EXC_BAD_ACCESS,因為你訪問了一塊已經不屬于你的內存。

4. 什么是空指針?

空指針不同于野指針,他是一個沒有指向任何內存的指針,空指針是有效指針,值為nil,NULL,Nil,0等,給空指針發送消息不會報錯,不會響應消息;

5. OC對象的內存管理機制?

在iOS中,使用引用計數來管理OC對象的內存

一個新創建的OC對象引用計數默認是1,當引用計數減為0,OC對象就會銷毀,釋放其占用的內存空間

調用retain會讓OC對象的引用計數+1,調用release會讓OC對象的引用計數-1

內存管理的經驗總結

當調用alloc、new、copy、mutableCopy方法返回了一個對象,在不需要這個對象時,要調用release或者autorelease來釋放它

想擁有某個對象,就讓它的引用計數+1;不想再擁有某個對象,就讓它的引用計數-1

可以通過以下私有函數來查看自動釋放池的情況

extern void _objc_autoreleasePoolPrint(void);

6. OC中有GC垃圾回收機制嗎?,iPhone上GC嗎?

垃圾回收(GC),就是程序中用于處理廢棄不用的內存對象的機制,防止內存泄露

OC本身是支持垃圾回頭得,不過只支持MAC OSX平臺, iOS 平臺不支持

7.在OC中與 Alloc 語義相反的是 release 還是 dealloc?

alloc 與 dealloc 語義相反,alloc 是創建變量,dealloc是釋放變量

retain 與 release 語義相反, retain 保留一個對象,引用計數器+1, release 使引用計數器 -1;

8.什么是內存溢出?

當程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個int,但給它存了long才能存下的數,那就是內存溢出。

9.內存區域分布

在iOS開發過程中,為了合理的分配有限的內存空間,將內存區域分為五個區,由低地址向高地址分類分別是:代碼區、常量區、全局靜態區、堆、棧。

代碼段 -- 程序編譯產生的二進制的數據

常量區 -- 存儲常量數據,通常程序結束后由系統自動釋放

全局靜態區 -- 全局區又可分為未初始化全局區:.bss段和初始化全局區:data段。全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域,在程序結束后有系統釋放。

堆(heap) -- 程序運行過程中,動態分配的內存

棧(stack) -- 存放局部變量,臨時變量

10.堆區和棧取的區別

按管理方式分

對于棧來講,是由系統編譯器自動管理,不需要程序員手動管理

對于堆來講,釋放工作由程序員手動管理,不及時回收容易產生內存泄露

按分配方式分

堆是動態分配和回收內存的,沒有靜態分配的堆

棧有兩種分配方式:靜態分配和動態分配

靜態分配是系統編譯器完成的,比如局部變量的分配

動態分配是有alloc函數進行分配的,但是棧的動態分配和堆是不同的,它的動 態分配也由系統編譯器進行釋放,不需要程序員手動管理

11.怎么保證多人開發進行內存泄露的檢查.

使用Analyze進行代碼的靜態分析

為避免不必要的麻煩, 多人開發時盡量使用ARC

使用leaks 進行內存泄漏檢測

使用一些三方工具

12.block在ARC中和MRC中的用法有什么區別,需要注意什么?

對于沒有引用外部變量的Block,無論在ARC還是非ARC下,類型都是NSGlobalBlock,這種類型的block可以理解成一種全局的block,不 需要考慮作用域問題。同時,對他進行Copy或者Retain操作也是無效的

都需要應注意避免循環引用,ARC 下使用__weak 來解決,MRC下使用__Block 來解決;

13.OC 如何對內存管理解決方法?

Objective-C的內存管理主要有三種方式 自動內存管理、手動內存管理、自動釋放池。

自動內存計數

手動內存計數:

自動釋放池:

14.ARC 都幫我們做了什么?

LLVM + Runtime 會為我們代碼自動插入 retain 和 release 以及 autorelease等代碼,不需要我們手動管理

15.weak指針的實現原理

Runtime維護了一個weak表,用于存儲指向某個對象的所有weak指針。weak表其實是一個hash(哈希)表,Key是所指對象的地址,Value是weak指針的地址(這個地址的值是所指對象的地址)數組。

runtime對注冊的類, 會進行布局,對于weak對象會放入一個hash表中。 用weak指向的對象內存地址作為key,當此對象的引用計數為0的時候會dealloc,假如weak指向的對象內存地址是a,那么就會以a為鍵, 在這個weak表中搜索,找到所有以a為鍵的weak對象,從而設置為nil。

16.方法里有局部對象,出了方法后會立即釋放嗎

如果是普通的 局部對象 會立即釋放

如果是放在了 autoreleasePool 自動釋放池,在 runloop 迭代結束的時候釋放

17.MRC情況下怎么做單例模式

創建單例設計模式的基本步驟 : ·

聲明一個單件對象的靜態實例,并初始化為nil。

創建一個類的類工廠方法,當且僅當這個類的實例為nil時生成一個該類 的實例

實現NScopying協議, 覆蓋allocWithZone:方法,確保用戶在直接分配和 初始化對象時,不會產 生另一個對象。

覆蓋release、autorelease、retain、retainCount方法, 以此確保單例的 狀態。

在多線程的環境中,注意使用@synchronized關鍵字或GCD,確保靜態實 例被正確的創建和初始化。

18.非OC對象如何管理內存?

非OC對象,其需要手動執行釋放操作例:CGImageRelease(ref),否則會造成大量的內存泄漏導致程序崩潰。其他的對于CoreFoundation框架下的某些對象或變量需要手動釋放、C語言代碼中的malloc等需要對應free。

19. CADisplayLink、NSTimer會出現的問題,以及解決辦法?

問題:

CADisplayLink、NSTimer會對target產生強引用,如果target又對它們產生強引用,那么就會引發循環引用

CADisplayLink、NSTimer都是基于 runloop 實現的.runloop 會對 CADisplayLink、NSTimer進行強引用, CADisplayLink、NSTimer又 會對 target 進行引用,造成循環引用

解決方案1.使用block

// 內部使用 WeakSelf,并在視圖消失前,關閉定時器__weak__typeof(self)weakSelf =self;NSTimer* timer = [NSTimertimerWithTimeInterval:1repeats:YESblock:^(NSTimer* _Nonnull timer) {NSLog(@"timer");}];self.timer= timer;[[NSRunLoopcurrentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];

解決方案2.使用代理對象(NSProxy)

image.png

.h// 解決循環引用問題@interfaceMyProxy:NSProxy- (instancetype)initWithObjc:(id)objc;+ (instancetype)proxyWithObjc:(id)objc;.m@interfaceMyProxy()@property(nonatomic,weak)idobjc;@end@implementationMyProxy- (instancetype)initWithObjc:(id)objc{self.objc = objc;returnself;}+ (instancetype)proxyWithObjc:(id)objc{return[[selfalloc] initWithObjc:objc];}- (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector {return[self.objc methodSignatureForSelector:aSelector];}- (void)forwardInvocation:(NSInvocation*)invocation {if([self.objc respondsToSelector:invocation.selector]) {? ? ? ? [invocation invokeWithTarget:self.objc];? ? }}

使用方法:

NSTimer* timer = [NSTimertimerWithTimeInterval:1target:[TimerProxy proxyWithTarget:self]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? selector:@selector(test1)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? userInfo:nilrepeats:YES];self.timer = timer;[[NSRunLoopcurrentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

20.什么是Tagged Pointer?

從64bit開始,iOS引入了Tagged Pointer技術,用于優化NSNumber、NSDate、NSString等小對象的存儲

在沒有使用Tagged Pointer之前, NSNumber等對象需要動態分配內存、維護引用計數等,NSNumber指針存儲的是堆中NSNumber對象的地址值

使用Tagged Pointer之后,NSNumber指針里面存儲的數據變成了:Tag + Data,也就是將數據直接存儲在了指針中

當指針不夠存儲數據時,才會使用動態分配內存的方式來存儲數據

21.copy和mutableCopy區別

image.png

22. 內存泄漏可能會出現的幾種原因?

第一種可能:第三方框架不當使用;

第二種可能:block循環引用;

第三種可能:delegate循環引用;

第四種可能:NSTimer循環引用

第五種可能:非OC對象內存處理

第六種可能:地圖類處理

第七種可能:大次數循環內存暴漲

23. ARC下什么樣的對象由 Autoreleasepool 管理

當使用alloc/new/copy/mutableCopy開始的方法進行初始化時,會生成并持有對象(也就是不需要pool管理,系統會自動的幫他在合適位置release),不需要pool進行管理

一般類方法創建的對象需要使用Autoreleasepool進管理

24. 如何實現AutoreleasePool?

AutoreleasePool(自動釋放池)其實并沒有自身的結構,他是基于多個AutoreleasePoolPage(一個C++類)以雙向鏈表組合起來的結構; 可以通過 push操作添加對象,pod 操作彈出對象,以及通過 release 操作釋放對象;

25. AutoreleasePoolPage的結構?以及如何 push 和 pod 的?

image.png

調用push方法會將一個POOL_BOUNDARY入棧,并且返回其存放的內存地址

調用pop方法時傳入一個POOL_BOUNDARY的內存地址,會從最后一個入棧的對象開始發送release消息,直到遇到這個POOL_BOUNDARY

id *next指向了下一個能存放autorelease對象地址的區域

26.Autoreleasepool 與 Runloop 的關系

主線程默認為我們開啟 Runloop,Runloop 會自動幫我們創建Autoreleasepool,并進行Push、Pop 等操作來進行內存管理

iOS在主線程的Runloop中注冊了2個Observer

第1個Observer監聽了kCFRunLoopEntry事件,會調用objc_autoreleasePoolPush()

第2個Observer 監聽了kCFRunLoopBeforeWaiting事件,會調用objc_autoreleasePoolPop()、objc_autoreleasePoolPush()監聽了kCFRunLoopBeforeExit事件,會調用objc_autoreleasePoolPop()

27.子線程默認不會開啟 Runloop,那出現 Autorelease 對象如何處理?不手動處理會內存泄漏嗎?

在子線程你創建了 Pool 的話,產生的 Autorelease 對象就會交給 pool 去管理。如果你沒有創建 Pool ,但是產生了 Autorelease 對象,就會調用 autoreleaseNoPage 方法。在這個方法中,會自動幫你創建一個 hotpage(hotPage 可以理解為當前正在使用的 AutoreleasePoolPage,如果你還是不理解,可以先看看 Autoreleasepool 的源代碼,再來看這個問題 ),并調用 page->add(obj)將對象添加到 AutoreleasePoolPage 的棧中,也就是說你不進行手動的內存管理,也不會內存泄漏啦!StackOverFlow 的作者也說道,這個是 OS X 10.9+和 iOS 7+ 才加入的特性。

28.以下代碼會有什么問題嗎?

Person *p = [[[[Person alloc]init] autorelease] autorelease];

以上代碼會導致程序崩潰,連續調用2次 autorelease,對象被加入自動釋放吃2次, 在釋放時候,此一次釋放對象就已經銷毀了,第二次再釋放就會崩潰;

29.以下代碼運行會有是問題?

dispatch_queue_tqueue = dispatch_get_global_queue(0,0);for(inti=0; i<10000; i++) {dispatch_async(queue, ^{NSString* str = [NSStringstringWithFormat:@"abcdefghijklmn1234566!@#$"];? ? })}dispatch_queue_tqueue = dispatch_get_global_queue(0,0);for(inti=0; i<10000; i++) {dispatch_async(queue, ^{NSString* str = [NSStringstringWithFormat:@"abc!"];? ? })}

第一個內存會暴漲,str 會不行的創建,由于是靜態方法,會加入到自動釋放池,會延遲釋放,造成內存暴漲

第二個內存固定,會使用 Tagged Pointer 將值存在地址中

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容

  • Swift1> Swift和OC的區別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,120評論 1 32
  • 內存管理 簡述OC中內存管理機制。與retain配對使用的方法是dealloc還是release,為什么?需要與a...
    丶逐漸閱讀 1,981評論 1 16
  • 內存管理 ARC處理原理 ARC是Objective-C編譯器的特性,而不是運行時特性或者垃圾回收機制,ARC所做...
    b485c88ab697閱讀 11,227評論 3 47
  • 前言 什么是內存管理?是指軟件運行時對計算機內存資源的分配和使用的技術。其最主要的目的是如何高效,快速的分配,并且...
    齊滇大圣閱讀 31,559評論 8 96
  • 下車 彩虹步道(20分鐘) 大樹前分組毛毛蟲(30分鐘) 上廁所(15分鐘) 拉圈介紹(四位老師、志愿者)(10分...
    櫻桃繪本課閱讀 171評論 0 0