iOS 應用崩潰超 90% 由內存問題引起。在龐大工程中排查極難,掌握常見陷阱可顯著降低出錯率。內存問題主要表現為:內存洩漏、野指針、過度釋放。本文解析兩道經典面試題,揭示 autorelease 機制與指針重賦值的隱患。
@autoreleasepool {
for (long i = 0; i < largeNumber; i++) {
Person *per = [[Person alloc] init];
[per autorelease];
}
}
表面上 alloc 與 autorelease 配對,符合內存管理原則。但 autorelease 並非立即釋放,而是將對象放入最近的自動釋放池,池銷毀時才發送 release。若 largeNumber 極大,循環期間對象堆積在池中,導致內存飆升甚至 OOM。
@autoreleasepool {
for (long i = 0; i < largeNumber; i++) {
@autoreleasepool {
Person *per = [[Person alloc] init];
[per autorelease];
} // 每次迭代結束,內層池銷毀,對象及時釋放
}
}
關鍵點:在循環內部創建新的 @autoreleasepool,確保每次迭代結束時釋放當前對象,避免內存累積。
@autoreleasepool {
NSString *per = [[NSString alloc] init];
[per retain];
[per retain];
per = @"aa";
[per release];
[per release];
[per release];
}
per = @"aa" 使指針指向常量區字面量,原 alloc 的堆對象失去引用,無法釋放,造成洩漏。release 作用於常量區對象,常量區無需手動管理,會導致崩潰或未定義行為。若需重新賦值,應先釋放原對象:
[per release]; // 釋放原 alloc 對象 [per release]; // 對應兩次 retain per = @"aa"; // 指向常量區,無需 release
理解運行時機制,而非死記規則,才能寫出健壯的 Objective-C 代碼。