華山論劍之iOS內(nèi)存,內(nèi)存管理,copy(拷貝)

我想大部分人都知道通常一個(gè)程序員會(huì)具有的美德循捺。當(dāng)然了幕垦,有三種:懶惰,暴躁已旧,傲慢。 ----Perl語言發(fā)明者Larry Wall

我想不管是iOS的,還是Java的初學(xué)者,內(nèi)存算得上心中的一個(gè)永遠(yuǎn)抹不去的痛吧,當(dāng)時(shí)作為初學(xué)者的我也是一度苦惱,不知道該如何理解這個(gè)內(nèi)存,隨著不斷的學(xué)習(xí),自己對(duì)內(nèi)存也有更深的了解.



內(nèi)存

說到內(nèi)存,不能不說一下內(nèi)存的分區(qū),內(nèi)存總共分為五大區(qū),分別是棧區(qū) 堆區(qū) 靜態(tài)區(qū) 常量區(qū) 代碼區(qū),五個(gè)區(qū)是按照內(nèi)存地址從大到小分配的.
內(nèi)存的分區(qū)示意圖
各個(gè)分區(qū)的的特點(diǎn)
其實(shí)我們最常用的還是棧區(qū)和堆區(qū)的內(nèi)存,然后首先來看一下棧區(qū)內(nèi)存的特點(diǎn)吧,

1.棧區(qū)內(nèi)存

 1.局部變量的存儲(chǔ)空間基本都是棧區(qū),局部變量在函數(shù),循環(huán),分支中定義
 
 2.在棧區(qū)的存儲(chǔ)空間由高向低分配,從低向高存儲(chǔ).!!
 
 3.棧區(qū)內(nèi)存由系統(tǒng)負(fù)責(zé)分配和回收,程序員開發(fā)者沒有管理權(quán)限.
 
 4.當(dāng)函數(shù),循環(huán),分支執(zhí)行結(jié)束后,局部變量的生命周期就結(jié)束了.之后不能再進(jìn)行使用,由系統(tǒng)銷毀
 
 5.棧底,棧頂:棧底是棧區(qū)內(nèi)存的起始位置,先定義的變量所占用的內(nèi)存,從棧底開始分配,后定義的變量所占用的內(nèi)存,逐漸向棧頂分配.
 
 6.入棧,出棧:入棧,定義新的局部變量,分配存儲(chǔ)空間.出棧,局部變量被銷毀,存儲(chǔ)空間被收回.
 
 7.棧的特點(diǎn):先進(jìn)后出,后進(jìn)先出.例如:子彈夾添加子彈,打出子彈.

2.堆區(qū)內(nèi)存

 1.由開發(fā)者負(fù)責(zé)分配和回收.
 
 2.忘記回收會(huì)造成泄漏.
 
 3.程序運(yùn)行結(jié)束后,需要及時(shí)回收堆內(nèi)存,但是如果不能及時(shí)回收堆內(nèi)存程序運(yùn)行期間可能會(huì)因?yàn)閮?nèi)存泄漏造成堆內(nèi)存被全部使用,導(dǎo)致程序無法使用.

3.常量區(qū)內(nèi)存

1.常量存儲(chǔ)在常量區(qū),例如:常量數(shù)字,常量字符串,常量字符,

2.常量區(qū)存儲(chǔ)空間由系統(tǒng)分配和回收

3.程序運(yùn)行結(jié)束后,常量區(qū)的存儲(chǔ)空間被回收

4.常量區(qū)的數(shù)據(jù)只能讀取,不能修改,修改的話會(huì)造成崩潰.

4.靜態(tài)區(qū)內(nèi)存

 1.全局變量,使用static修飾的局部變量,都存儲(chǔ)在靜態(tài)區(qū).
 
 2.靜態(tài)區(qū)的存儲(chǔ)空間由系統(tǒng)分配和回收.
 
 3.程序運(yùn)行結(jié)束后,靜態(tài)區(qū)的存儲(chǔ)空間被回收,靜態(tài)變量的生命周期和程序一樣長(zhǎng).
 
 4.靜態(tài)變量只能初始化一次,在編譯時(shí)進(jìn)行初始化,運(yùn)行時(shí)可以修改值
 
 5.靜態(tài)變量如果沒有設(shè)置初始值,默認(rèn)為0.
5.代碼區(qū)內(nèi)存
 1.由系統(tǒng)分配和回收
 
 2.程序運(yùn)行結(jié)束之后,由系統(tǒng)回收分配過的內(nèi)存存儲(chǔ)空間

內(nèi)存管理

上面我們說到了內(nèi)存的五大區(qū),現(xiàn)在我從內(nèi)存的管理來說一下內(nèi)存,為什么我們開發(fā)應(yīng)用的時(shí)候要要注意內(nèi)存呢?由于移動(dòng)設(shè)備的內(nèi)存有限,所以每一個(gè)APP應(yīng)用程序的內(nèi)存也是有限的,App所占用的內(nèi)存較多時(shí),系統(tǒng)就會(huì)發(fā)出內(nèi)存警告.為了節(jié)省內(nèi)存的使用.所以我們就要使用到內(nèi)存管理,就是當(dāng)對(duì)象不再被使用的時(shí)候,我們要對(duì)其內(nèi)存及時(shí)的進(jìn)行回收.
內(nèi)存管理這一塊我要說的是我們?cè)贛RC(Manual Reference Counting)環(huán)境下需要手動(dòng)管理堆區(qū)的內(nèi)存,進(jìn)行release操作等,但是在 ARC(Automatic Reference Counting)環(huán)境下,我們不需要手動(dòng)管理我們的內(nèi)存.首先我們需要看一下如何切換ARC環(huán)境和MRC環(huán)境.

首選我們需要打開工程的配置面板,然后Build setting面板中搜索auto(自動(dòng))關(guān)鍵的字樣,然后就可以查找到ARC環(huán)境的切換選項(xiàng)了

ARC環(huán)境切換示意圖
下面我就說一下內(nèi)存管理的核心,內(nèi)存管理的核心就是引用計(jì)數(shù)的加減,引用計(jì)數(shù)相當(dāng)于對(duì)象的一個(gè)屬性,當(dāng)然了,這個(gè)屬性是不需要我們手動(dòng)創(chuàng)建的,系統(tǒng)會(huì)幫每一個(gè)對(duì)象進(jìn)行創(chuàng)建的.
引用計(jì)數(shù)示意圖
引用計(jì)數(shù)器的作用:用來判斷對(duì)象是否應(yīng)該回收內(nèi)存空間,當(dāng)引用計(jì)數(shù)器為0時(shí),此時(shí)需要回收對(duì)象的內(nèi)存空間.
引用計(jì)數(shù)器的操作:
retain 引用計(jì)數(shù)器 +1
release 引用計(jì)數(shù)器 -1
retainCount 得到引用計(jì)數(shù)器的值
如果一個(gè)對(duì)象被釋放的時(shí)候,引用計(jì)數(shù)為0了,就會(huì)使用一個(gè)方法,析構(gòu)函數(shù)dealloc;
然后,我們就看一下內(nèi)存管理的黃金法則,

內(nèi)存黃金法則:

誰alloc,誰release!(包括new);

誰retain,誰release!

(retain) 引用計(jì)數(shù)+1

(release) 引用計(jì)數(shù)-1

誰copy,誰release!


野指針與內(nèi)存泄露

說到內(nèi)存管理就不得不說一下內(nèi)存泄露和野指針問題.
內(nèi)存泄漏

用動(dòng)態(tài)存儲(chǔ)分配函數(shù)動(dòng)態(tài)開辟的空間召娜,在使用完畢后未釋放运褪,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元,不能被任何程序再次使用玖瘸,直到程序結(jié)束秸讹。即所謂內(nèi)存泄漏。
注意:內(nèi)存泄漏是指堆內(nèi)存的泄漏店读。
 簡(jiǎn)單的說就是申請(qǐng)了一塊內(nèi)存空間嗦枢,使用完畢后沒有釋放掉。它的一般表現(xiàn)方式是程序運(yùn)行時(shí)間越長(zhǎng)屯断,占用內(nèi)存越多文虏,最終用盡全部?jī)?nèi)存,整個(gè)系統(tǒng)崩潰殖演。由程序申請(qǐng)的一塊內(nèi)存氧秘,且沒有任何一個(gè)指針指向它,那么這塊內(nèi)存就泄露了趴久。

野指針

“野指針”不是NULL指針丸相,是未初始化或未清零的指針,他指向的內(nèi)存地址不是程序員想要的彼棍。人們一般不會(huì)錯(cuò)用NULL指針灭忠,因?yàn)橛胕f語句很容易判斷座硕。但是“野指針”是很危險(xiǎn)的弛作,if語句對(duì)它不起作用。野指針的成因主要有兩種:
  一华匾、指針變量沒有被初始化映琳。任何指針變量剛被創(chuàng)建時(shí)不會(huì)自動(dòng)成為NULL指針,它的缺省值是隨機(jī)的蜘拉,它會(huì)亂指一氣萨西。所以,指針變量在創(chuàng)建的同時(shí)應(yīng)當(dāng)被初始化旭旭,要么將指針設(shè)置為NULL谎脯,要么讓它指向合法的內(nèi)存。
  二您机、指針p被free或者delete之后穿肄,沒有置為NULL年局,讓人誤以為p是個(gè)合法的指針。別看free和delete的名字惡狠狠的(尤其是delete)咸产,它們只是把指針?biāo)傅膬?nèi)存給釋放掉矢否,但并沒有把指針本身干掉。通常會(huì)用語句if (p != NULL)進(jìn)行防錯(cuò)處理脑溢。很遺憾僵朗,此時(shí)if語句起不到防錯(cuò)作用,因?yàn)榧幢鉷不是NULL指針屑彻,它也不指向合法的內(nèi)存塊验庙。

#pragma mark---研究簡(jiǎn)單的野指針---
        Person *p = [Person new];
        
        //使用KVC對(duì)屬性進(jìn)行賦值
        [p setValue:@"棟棟" forKey:@"name"];
        [p  retain];

        //調(diào)用方法
        [p eat];
  
        //釋放
        [p release];

        //此處是野指針,在正常的情況下是可以訪問的.如果想要查找野指針,就要打開僵尸模式,editscheme->diagnostics->zombie
        [p eat];

        [p release];//如果不release就會(huì)產(chǎn)生內(nèi)存泄漏.

上面說到了僵尸模式,然后我們就看看如何開啟僵尸模式,檢測(cè)野指針的存在.

開啟僵尸模式


拷貝

對(duì)于拷貝,也是讓大多數(shù)人頭疼的,因?yàn)榭截惪局局桶炎约航o弄糊涂了,所以,今天最后我還要說一下這個(gè)copy相關(guān)的問題,首先拷貝分為可變拷貝和不可變的拷貝.來看一下實(shí)際的范例吧

NSString * p1 =@"Jobs";
        
        NSString *p2 = [NSString stringWithFormat:@"wang"];
        
        NSString *p3 = [[NSString alloc]initWithString:p1];
        
        NSString *p4 = [NSString stringWithString:p1];
        
        NSLog(@"%@ ----- %p",p1,p1);
        
        NSLog(@"%@ ----- %p",p2,p2);
        
        NSLog(@"%@ ----- %p",p3,p3);
        
        NSLog(@"%@ ----- %p",p4,p4);

        NSLog(@"%p",p1);

然后打印結(jié)果是這樣的..


打印結(jié)果

這樣我們不難發(fā)現(xiàn),p3和p4只是指針的重指向而已.

不可變拷貝

下面就是不可變拷貝,當(dāng)我們這樣使用的時(shí)候 程序是會(huì)crash掉的,雖然p2的類型是可變的字符串對(duì)象,由于p2是p1進(jìn)行不可變出來的,其實(shí)相當(dāng)于p2指向了p1,通過地址我們不難發(fā)現(xiàn)p1和p2指針指向的是相同的一個(gè)地址.

        NSString * p1 =@"Jobs";

        NSLog(@"%p",p1);
        
        //可變字符串對(duì)象  指向   不可變拷貝的數(shù)據(jù)
        NSMutableString * p2 = [p1 copy];
        
        NSLog(@"%p",p2);
        
        //如果上面使用的是 copy,那么此處就會(huì)crash,如果使用的是,mutableCopy那么將會(huì)改變
        
        [p2 appendString:@"steve"];
運(yùn)行的結(jié)果

</br>

可變拷貝

如果我們將上面的過程換成可變的拷貝,然后再進(jìn)行字符串的拼接會(huì)有什么情況的產(chǎn)生呢?

        NSString * p1 =@"Jobs";

        NSLog(@"%p",p1);
        
        //可變字符串對(duì)象  指向   不可變拷貝的數(shù)據(jù)
        NSMutableString * p2 = [p1 mutableCopy];
        
        NSLog(@"%p",p2);
        
        //如果上面使用的是 copy,那么此處就會(huì)crash,如果使用的是,mutableCopy那么將會(huì)改變
        
        [p2 appendString:@"steve"];
可變拷貝的打印結(jié)果

通過上面的兩個(gè)實(shí)例,我們簡(jiǎn)單的對(duì)可變拷貝和不可變拷貝做一下總結(jié),用于以后的工作中

上述總結(jié):

copy(不可變拷貝),如果使用了不可變拷貝,那么接收的對(duì)象不管是可變對(duì)象還是不可變的對(duì)象,都不能改變拷貝過來的內(nèi)容

mutableCopy(可變拷貝),如果使用了可變拷貝,那么接收對(duì)象不管是可變的還是不可變的對(duì)象,都可以改變拷貝過來的內(nèi)容


淺拷貝和深拷貝

對(duì)于淺拷貝和深拷貝,其實(shí)就是拷貝對(duì)象的區(qū)別,淺拷貝拷貝的是地址,而深拷貝拷貝的是對(duì)象的本身.

#pragma mark---怎么判斷深拷貝----
        
        //通過兩個(gè)對(duì)象的地址來判斷,如果地址不同,那么就是深拷貝.
        
#pragma mark---怎么判斷淺拷貝----
        
        //通過兩個(gè)對(duì)象的地址來判斷,如果地址相同,那么就是淺拷貝.
        

這里我給大家附加上一道面試題,來提高大家對(duì)copy的理解

#pragma mark--- 面試題 ---
        
        //1.你怎么樣理解深拷貝和淺拷貝.
        //淺拷貝:就如同人和影子,在內(nèi)存,人沒影子就沒了,影子沒了人就沒了.就是操作的同一個(gè)空間.
        //深拷貝:就如同人和克隆,在內(nèi)存中,人沒了克隆還在,克隆沒有,人還在.就是操作的不同的空間.
        
        //2.如何對(duì)深拷貝和淺拷貝進(jìn)行內(nèi)存釋放
        //淺拷貝:釋放一個(gè)即可.因?yàn)獒尫拍膫€(gè)對(duì)象,都是同一個(gè)空間.
        //深拷貝:釋放全部,因?yàn)槭莾蓚€(gè)對(duì)象,而且是兩個(gè)空間.




今天我就先說到這,后期將說一下,對(duì)象屬性的實(shí)現(xiàn)原理,如果您喜歡這篇文章就點(diǎn)個(gè) '喜歡' 吧,不要打賞,只求 ' 喜歡 ',謝謝各位看官了.


參考博客原文:http://blog.csdn.net/dangercheng/article/details/12618161

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市社牲,隨后出現(xiàn)的幾起案子粪薛,更是在濱河造成了極大的恐慌,老刑警劉巖搏恤,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件违寿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡熟空,警方通過查閱死者的電腦和手機(jī)藤巢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來息罗,“玉大人掂咒,你說我怎么就攤上這事÷鹾恚” “怎么了绍刮?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)挨摸。 經(jīng)常有香客問我录淡,道長(zhǎng),這世上最難降的妖魔是什么油坝? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮刨裆,結(jié)果婚禮上澈圈,老公的妹妹穿的比我還像新娘。我一直安慰自己帆啃,他們只是感情好瞬女,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著努潘,像睡著了一般诽偷。 火紅的嫁衣襯著肌膚如雪坤学。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天报慕,我揣著相機(jī)與錄音深浮,去河邊找鬼。 笑死眠冈,一個(gè)胖子當(dāng)著我的面吹牛飞苇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜗顽,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼布卡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了雇盖?” 一聲冷哼從身側(cè)響起忿等,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎崔挖,沒想到半個(gè)月后贸街,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虚汛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年匾浪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卷哩。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛋辈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出将谊,到底是詐尸還是另有隱情冷溶,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布尊浓,位于F島的核電站逞频,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏栋齿。R本人自食惡果不足惜苗胀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瓦堵。 院中可真熱鬧基协,春花似錦、人聲如沸菇用。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惋鸥。三九已至杂穷,卻和暖如春悍缠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耐量。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工飞蚓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拴鸵。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓玷坠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親劲藐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子八堡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 內(nèi)存管理 簡(jiǎn)述OC中內(nèi)存管理機(jī)制。與retain配對(duì)使用的方法是dealloc還是release聘芜,為什么兄渺?需要與a...
    丶逐漸閱讀 1,948評(píng)論 1 16
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 1,962評(píng)論 0 7
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理汰现。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場(chǎng)景挂谍。SDWebImage的原...
    LZM輪回閱讀 2,004評(píng)論 0 12
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,284評(píng)論 0 6
  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運(yùn)行時(shí)分配內(nèi)存(比如創(chuàng)建一個(gè)對(duì)象,會(huì)增加內(nèi)存占用)與...
    蚊香醬閱讀 5,694評(píng)論 8 119