內存管理系列文章:ios
OC底層實現其實都是C語言的代碼,因此想深刻理解iOS的內存管理機制,能夠經過了解C語言的內存管理來進一步熟悉OC的內存管理。程序員
RAM和ROM的區別bash
在瞭解OC的內存分配以前,先看下app的加載過程:數據結構
畫圖工具沒找到太合適的,粗略的作了一張圖,經過如下這張圖對內存佈局有個大概認識:app
程序代碼區:代碼區用來存放函數體的二進制代碼,程序結束後由系統釋放函數
常量區: 常量區用來存放常量字符串等,程序結束後由系統釋放工具
靜態區:全局變量和靜態變量的存儲是放在一塊的,程序結束後由系統釋放佈局
全局變量和靜態變量要儘可能少用。由於這些變量在程序的生命週期中不會變釋放,比較容易佔用內存空間,不適合存儲比較大量的數據post
每個函數在執行的時候都會向操做系統索要資源,棧區就是函數運行時的內存,棧區中的變量由編譯器負責分配和釋放,內存隨着函數的運行分配,隨着函數的結束而釋放,由系統自動完成。測試
我的以爲主要弄清楚如下幾點
運行環境:選擇的模擬器是Iphone11 Pro Max
static int a = 10;
static int b;
- (void)viewDidLoad {
[super viewDidLoad];
/* 代碼段 */
IMP imp = method_getImplementation(class_getInstanceMethod(self.class, @selector(viewDidLoad)));
NSLog(@"【代碼段】==> 編譯以後的函數");
NSLog(@"imp --- %p", imp);
/* 數據段 */
static int c = 10;
static int d;
/* 常量區 */
NSString *str1 = @"腳底按摩"; // 直接寫出來的,不是經過方法建立的字符串,編譯時會生成爲【字符串常量】
NSString *str2 = @"精油推背";
NSLog(@"【數據段/常量區】==> 字符串常量");
NSLog(@"str1 --- %p", str1);
NSLog(@"str2 --- %p", str2);
/* 靜態初始化區 */
NSLog(@"【數據段/靜態區】==> 已初始化數據");
NSLog(@"c ------ %p", &c);
NSLog(@"a ------ %p", &a);
/* 靜態未初始化區 */
NSLog(@"【數據段/靜態區】==> 未初始化數據");
NSLog(@"d ------ %p", &d);
NSLog(@"b ------ %p", &b);
/* 堆 */
NSObject *obj = [[NSObject alloc] init];
NSString *str3 = [NSString stringWithFormat:@"%@", @"測試字符串是否在堆上"];
NSLog(@"【堆】==> 實例對象"); // 分配的內存空間地址【愈來愈大】,不連續的
NSLog(@"obj ---- %p", obj);
NSLog(@"str3 --- %p", str3);
/* 棧 */
int e = 20;
int f;
NSLog(@"【棧】==> 局部變量"); // 分配的內存空間地址【愈來愈小】,是連續的,無論有沒有初始化都會分配
NSLog(@"e ------ %p", &e);
NSLog(@"f ------ %p", &f);
}
// 打印結果
2020-03-24 23:05:05.707713+0800 03-內存管理-內存佈局[3812:249391] 【代碼段】==> 編譯以後的函數
2020-03-24 23:05:05.707854+0800 03-內存管理-內存佈局[3812:249391] imp --- 0x10f55cae0
2020-03-24 23:05:05.707985+0800 03-內存管理-內存佈局[3812:249391] 【數據段/常量區】==> 字符串常量
2020-03-24 23:05:05.708091+0800 03-內存管理-內存佈局[3812:249391] str1 --- 0x10f55f060
2020-03-24 23:05:05.708197+0800 03-內存管理-內存佈局[3812:249391] str2 --- 0x10f55f080
2020-03-24 23:05:05.708307+0800 03-內存管理-內存佈局[3812:249391] 【數據段/靜態區】==> 已初始化數據
2020-03-24 23:05:05.708411+0800 03-內存管理-內存佈局[3812:249391] c ------ 0x10f5614c0
2020-03-24 23:05:05.708510+0800 03-內存管理-內存佈局[3812:249391] a ------ 0x10f5614c4
2020-03-24 23:05:05.708621+0800 03-內存管理-內存佈局[3812:249391] 【數據段/靜態區】==> 未初始化數據
2020-03-24 23:05:05.708723+0800 03-內存管理-內存佈局[3812:249391] d ------ 0x10f561648
2020-03-24 23:05:05.708982+0800 03-內存管理-內存佈局[3812:249391] b ------ 0x10f56164c
2020-03-24 23:05:05.719411+0800 03-內存管理-內存佈局[3812:249391] 【堆】==> 實例對象
2020-03-24 23:05:05.719575+0800 03-內存管理-內存佈局[3812:249391] obj ---- 0x600002a05610
2020-03-24 23:05:05.719692+0800 03-內存管理-內存佈局[3812:249391] str3 --- 0x600002642400
2020-03-24 23:05:05.719810+0800 03-內存管理-內存佈局[3812:249391] 【棧】==> 局部變量
2020-03-24 23:05:05.719932+0800 03-內存管理-內存佈局[3812:249391] e ------ 0x7ffee06a10c4
2020-03-24 23:05:05.720063+0800 03-內存管理-內存佈局[3812:249391] f ------ 0x7ffee06a10c0
複製代碼
NSObject *obj = [[NSObject alloc] init];
NSString *str3 = [NSString stringWithFormat:@"%@", @"測試字符串是否在堆上"];
2020-03-24 23:05:05.719411+0800 03-內存管理-內存佈局[3812:249391] 【堆】==> 實例對象
2020-03-24 23:05:05.719575+0800 03-內存管理-內存佈局[3812:249391] obj ---- 0x600002a05610
2020-03-24 23:05:05.719692+0800 03-內存管理-內存佈局[3812:249391] str3 --- 0x600002642400
複製代碼