iOS-內存管理就這麼簡單1

文明看博轉載是對自己的尊重也是對學者的鼓勵,歡迎討論

-------------iOS-圖說OC內存管理----------------

一.OC源代碼分解及到C語言的討論

在此我們來看一下語言的結構,把源代碼的編寫形式分解。把內存的組織分解,然後把源代碼的編寫映射到內存中的運行時,只要掌握源代碼的內存映射各個要素之間的對應關係,就能很好的掌握內存管理,思想很重要一切都爲樂coding服務。
一個條C語言的語句:

int number;
1.上面的語句聲明瞭一個int 類型的變量,這時候number的值是不確定的,number被編譯器編譯之後,number就是一個虛擬內存地址(可以想象,計算機資源這麼寶貴,不可能去花空間來儲存變量名的字符串,在源代碼層面變量名是給人看的,在編譯器的眼中任何的變量名,函數名,常量等都是虛擬地址)。


int number=8;
2.這就相當於把8的值放到number的虛擬內存中去。number是值類型,如果它是在函數中的話,當函數執行完成後,它的生命週期就結束了會被釋放,它的生命週期由它的作用域決定。


typedef struct TestStruct{
    int number;
}TestStrutType;


TestStrutType number;
    number.number =8;
<p class="p1"><span class="s1">NSLog</span><span class="s2">(</span><span class="s3">@"number=%d number.number=%d"</span><span class="s2">,&number,&number.</span><span class="s4">number</span><span class="s2">);</span></p>


運行結果:

2015-01-17 15:33:33.575 MemoryManager[816:32368] number=1587763888 number.number=1587763888



3.聲明一個結構體,用它來聲明一個number變量,並設置number變量中的number成員的值爲 8;被編譯之後其實結構體變量number和其成員變量都在同一個虛擬內存中,它們也是值類型,生命週期由它的作用域決定,說白了就是函數調用返回決定。說到這裏就得到一個結論,變量編譯之後是一個虛擬內存地址,而變量的類型決定了去怎樣讀取它的值。



    TestStrutType *number= malloc(sizeof(TestStrutType));
    number->number =8;

4.聲明一個TestStructType類型的指針變量number,並通過malloc手動分配對應類型大小的堆內存塊,並把堆內存塊的指針存放到棧上變量number指針變量的虛擬內存上,通過指針變量number給成員變量number賦值,這時候的數字8是存放在堆內存塊中的。當number指針變量所在的函數返回,也就是number的生命週期結束了,通過malloc分配的內存塊還在,它並沒有被釋放,這樣就會造成內存泄漏。棧上的內存變量會自動釋放,堆上的內存塊是手動分配的就要手動釋放,由於棧內存變量和堆內存塊的管理機制不相同,這就引出了內存管理問題。


NSObject *obj = [[NSObject alloc]init];

5.聲明一個NSObject類型的指針變量變量obj,指向一個NSObject類型的堆內存塊。[[NSObject alloc]init]本質上就是調用malloc函數分配一個NSObject類型大小的內存塊,並把它的堆內存虛擬地址賦值給棧上的指針變量obj,當obj所在的函數返回,也就是obj的生命週期結束了,這時obj被釋放了,但是[[NSObject alloc]init]分配的堆內存塊還在,這時就會出現內存泄漏的問題。由於堆內存的對象時手動釋放,什麼時候釋放,什麼時候不該釋放,就成了編程中要考慮的問題,如果提前釋放,當訪問對象時就會報錯,如果該釋放的時候沒有被釋放,就會造成內存浪費。Object-C語言採用的是引用計數的方式來達到內存管理的。上面都只是問題的鋪墊,下面我們將要了詳細的對引用計數的內存管理全面的講解。


在OC語言中最常用的語法格式是 (類型)*(指針變量) = ([[(類型)alloc]init])的形式來聲明變量的。下面我分把它分解來說明。首先從等號分開。等號左邊的是指針變量,等號右邊的是該類型的實例內存塊。等號左邊的是在棧上的虛擬內存上,等號右邊的是堆上的內存上。等號左邊的變量是自動管理的,等號右邊的內存塊是要編程人要手動的管理的。下面我們就把OC的常用的表達式模擬成一個場景:打一個比方(等號的左邊指針變量相當於一個人)(等號相當於把一根線交給人)(等號的右邊相當於飄在空中的氣球)(retain函數相當於retainCount加1)(release函數相當於retainCount 減1)(retainCount表示該氣球是不是要被銷燬掉,爲0銷燬,大於0保留),(autoReleasePool的變量相當於一個管理者)。於是通過上面的組合就得到下面的一些情景。

1.

NSObject *obj;   //表示有一個人出現了,但是這個人並沒有拉着氣球


2.

[[NSObject alloc]init];   //出現了一個氣球,並沒有任何人拉着它,但是它的retainCount爲1所以它不能背銷燬,(內存泄漏)


3.

NSObject *obj = [[NSObject alloc]init]; //obj這個人通過線拉着一個氣球





4.

[[[NSObject alloc]init] retain];   //出現了一個沒有線的氣球,但是它的retainCount爲2所以它不能背銷燬,(內存泄漏)



5.

[[[NSObject alloc]init] release];   //剛創建就要被銷燬的氣球




6.
NSObject *obj = [[NSObject alloc]init]; //obj這個人通過線拉着一個氣球
    [obj autorelease];                      //obj這個人把氣球的線交給了管理人員,retainCount不變,




7.

NSObject *obj = [[NSObject alloc]init]; //obj這個人通過線拉着一個氣球
    NSObject *obj2 = obj;                   //obj2這個人和obj這個人共用一根線共同的拉着個氣球,retainCount不變






8.

NSObject *obj = [[NSObject alloc]init]; //obj這個人通過線拉着一個氣球
    NSObject *obj2 = [obj retain];          //obj2這個人和obj這個人用不同的線拉着同一個球,retainCount爲2不變





9.

NSObject *obj = [[NSObject alloc]init]; //obj這個人通過線拉着一個氣球
    [obj release];                          //obj把線減掉 retainCount減1,如果retainCount爲0將會被銷燬


待續。。。。。。。。。。。。。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章