iOS內(nèi)存區(qū)域分布

說到iOS的內(nèi)存管理,大家首先想到的可能是引用計數(shù)相關(guān)的東西,而跟引用計數(shù)相關(guān)的內(nèi)存都是分布在堆區(qū)(heap),也就是說我們平時關(guān)注最多的部分都是堆區(qū)的內(nèi)存。其實在iOS系統(tǒng)中(其他操作系統(tǒng)也一樣),內(nèi)存的分布區(qū)域大致可以分為三個部分:棧區(qū)(stack),堆區(qū)(heap),和全局靜態(tài)區(qū)(global)。其中棧區(qū)主要存放局部變量和函數(shù)參數(shù)等相關(guān)變量,超出作用域之后自動釋放,堆區(qū)存放alloc,new等關(guān)鍵字生成的對象;全局靜態(tài)區(qū)主要存放靜態(tài)數(shù)據(jù),全局?jǐn)?shù)據(jù)和常量,程序運行之后一直存在。分布如下圖所示:


內(nèi)存分布-2.png

在說內(nèi)存分布之前,先來理一理幾個概念:靜態(tài)數(shù)據(jù),全局?jǐn)?shù)據(jù)和常量。定義在類外面的都是全局?jǐn)?shù)據(jù),前面加const的,就是常量數(shù)據(jù),加static的是靜態(tài)數(shù)據(jù)。


屏幕快照 2016-09-19 5.21.26 PM.png

通過字符串的初始化,來分析內(nèi)存的分布

    NSString* str1 = @"123";
    NSLog(@"str1 = %p, str1 = %@",str1,str1);
    NSString* str2 = @"123";
    NSLog(@"str2 = %p, str2 = %@",str2,str2);

    NSString* str3 = [[NSString alloc]initWithFormat:@"123"];
    NSLog(@"str3 = %p, str3 = %@",str3,str3);
    NSString* str4 = [[NSString alloc]initWithFormat:@"123"];
    NSLog(@"str4 = %p, str4 = %@",str4,str4);

    NSString* str5 = [[NSString alloc]initWithString:str3];
    NSLog(@"str5 = %p, str5 = %@",str5,str5);
    NSString* str6 = [[NSString alloc]initWithString:str3];
    NSLog(@"str6 = %p,str6 = %@",str6,str6);

打印結(jié)果如下:

屏幕快照 2016-09-19 5.56.25 PM.png

首先@"123"是字符串常量,被分配在內(nèi)存的常量區(qū); str2也指向了這個常量,所以str1和str2的對應(yīng)的指針是一樣的。str3指向了一個alloc出來的對象,這個對象是被分配在堆內(nèi)存上的,所以str3和str2對應(yīng)的指針不一樣了。可能大家會感到奇怪,str4也指向了一個alloc出來的對象,這個對象也是被分配在堆內(nèi)存上的,為什么會跟str3的指向相同呢?其實這是iOS系統(tǒng)對字符串內(nèi)存的優(yōu)化:如果一個字符串是通過一個字符串常量初始化而來的,那么這個字符串里面的值可以直接從常量區(qū)去拿,這樣就不需要為每一個在堆上面的字符串分配一塊兒新的內(nèi)存。str5和str6都是指向堆上面的內(nèi)存,并且是通過變量來初始化的,所以對應(yīng)的指針不一樣。

上面一大段文字說的都是指針對應(yīng)的指向,而str1--str6本身是一個指針,又都是在函數(shù)中定義的,是局部變量,所以被分配到棧區(qū)。綜上可以得出如下的內(nèi)存分布圖:

內(nèi)存分布-3.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容