Objective-C內存管理相關的面試題
iOS應用程序出現Crash(閃退),90%以上的原因是內存問題。在一個擁有數十個甚至是上百個類的工程裡,查找內存問題極其困難。了解內存常見問題,能幫我們減少出錯幾率。內存問題體現在三個方面:內存溢出、野指針異常,內存過渡釋放。
在面試過程中,面試官也經常會問到關於內存方面的問題,在這裡,我和大家分享兩個簡單地面試題。
面試題一:
@autoreleasepool {
for (long i = 0; i < largeNumber; i++) {
Person *per = [[Person alloc] init];
[per autorelease];
}
}
其中largeNumber是一個很大的數,這道題有內存問題麼?如果有請在不修改已經寫好代碼的情況下解決內存問題。
我們都知道,內存管理的原則:如果對一個對象使用了alloc、copy、retain,那麼你必須使用相應的release或者autorelease。
咋一看,這道題目有alloc,也有autorelease,兩者對應起來了,沒問題。但是我們來仔細推敲一下,autorelease雖然會使引用計數減一,但是它並不是立即減一,它的本質功能只是把對象放在離他最近的自動釋放池中,當自動釋放池銷毀了,才會向自動釋放池中的每一個對象發送release消息。那麼,這道題的問題就在autorelease這裡。因為largeNUmber是一個很大的數,autorelease又不能使引用計數立即減一,所以在循環結束前會造成內存溢出的問題。解決方案如下:
@autoreleasepool {
for (long i = 0; i < largeNumber; i++) {
@autoreleasepool {
Person *per = [[Person alloc] init];
[per autorelease];
}
}
}
在循環內部再加一個自動釋放池,這樣就能保證每創建一個對象就能及時釋放。
面試題二:
@autoreleasepool {
NSString *per = [[NSString alloc] init];
[per retain];
[per retain];
per = @"aa";
[per release];
[per release];
[per release];
}
這道題同樣有內存問題,存在如下問題,1.內存溢出問題。2.指向常量區的對象不用release。
我們來分析一下這道題,表面看起來,alloc,retain和release對應起來了,貌似沒什麼問題。但是我們分析一下per = @"aa"; 這條語句。指針變量per原本指向一塊開辟的堆區空間,但是經過重新給per賦值,那麼per的指向就發生了改變,由原來指向堆區空間,到指向常量區。指向常量區以後,再對per發送release消息,它就是對常量區釋放,而常量區根本就不用釋放,這樣就導致原來開辟的堆區空間沒有釋放,會造成內存溢出的問題。