日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IOS面试_1.浅析内存管理

發布時間:2025/7/14 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IOS面试_1.浅析内存管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為了開學的面試,就在博客里總結一下面試會問到的問題,今天就來談談內存管理,看到一篇文章非常不錯,http://vinceyuan.cnblogs.com/,深入淺出,推薦大家去看看!

?

  Objective-C使用一種(Retain Count)引用計數的機制來管理內存,在OC中,每個對象都持有自己的retain count,引用計數可以理解為就是一個計數器,當對象alloc創建的時候,會自動設置為1,當給對象發送retain消息的時候,引用計數會加1,當給對象發送release消息的時候,引用計數會減1,當引用計數為0的時候,對象會釋放所占用的內存,這就是內存管理的機制,聽起來比較容易吧,下面就進一步分析這種機制。

  首先,我們應該知道為什么要這樣做?我們經常在不同的對象中引用相同的對象,例如:假設我們用不同電腦遠程連接到同一臺服務器進行遠程操作,轉化成OC語言就是不同電腦對象引用相同的服務器對象,這時候有一臺電腦在服務器上敲了shutdown命令,讓服務器掛掉了,這時候我們所有電腦都連接不上去了,其他人就工作不了了,引用計數其實就像一個計數開關,只有當沒有電腦連接的時候,計數為0,才允許執行shutdown命令(非常理想狀態下,現實中可不要這樣做)。

  不同于java的GC回收機制,java中當沒有對象引用指向原先分配給某個對象的內存時,該內存便成為垃圾。JVM的一個系統級線程會自動釋放該內存塊,除了釋放沒用的對象,垃圾回收也可以清除內存記錄碎片。由于創建對象和垃圾回收器釋放丟棄對象所占的內存空間,內存會出現碎片。碎片是分配給對象的內存塊之間的空閑內存洞。碎片整理將所占用的堆內存移到堆的一端,JVM將整理出的內存分配給新的對象。OC中這種特有的retain count機制,給我們更多權限,讓開發者去控制對象釋放的時間以及如何去釋放,所以我們得更加小心,過早的釋放內存,可能會引起程序崩潰,長時間不釋放占用的內存,程序在運行一段時間后可能會發生內存泄露。

?

?  Objective-C采用了引用計數(retain count)。對象的內部保存一個數字,表示被引用的次數。例如,某個對象被兩個指針所指向(引用)那么它的retain count為2。需要銷毀對象的時候,不直接調用dealloc,而是調用release。release會讓retain count減1,只有retain count等于0,系統才會調用dealloc真正銷毀這個對象。

ClassA *obj1 = [[ClassA alloc] init];//對象生成時,retain count = 1[obj1 release]; //release使retain count減1,retain count = 0,dealloc自動被調用,對象被銷毀

 下面觀看一個例子

ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1 ClassA *obj2 = obj1; //retain count = 1 [obj1 hello]; //輸出hello [obj1 release]; //retain count = 0,對象被銷毀 [obj2 hello]; [obj2 release];

obj2引用了obj1,此時retain count為1,當obj1執行完消息釋放后,retain count=0,此時obj2變成了無效指針,這里再執行[obj2 release]會引起內存的過度釋放

所以一定要謹記,不是alloc創建,而是指針賦值的時候,一定要retain,拿到對象的所有權

ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1 ClassA *obj2 = obj1; //retain count = 1 [obj2 retain]; //retain count = 2 [obj1 hello]; //輸出hello [obj1 release]; //retain count = 2 – 1 = 1 [obj2 hello]; //輸出hello [obj2 release]; //retain count = 0,對象被銷毀

這樣寫的確可以解決問題,但是如果對象非常多得時候,這樣的操作會不會太繁瑣了點,有沒有簡單一點的解決辦法?所以oc引入了自動釋放池autorelease pool,這也不同于java的全自動垃圾回收

新生成的對象調用autorelease就可以了

ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1 但無需調用release

如果存在指針賦值,與上面的代碼也相似

ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1 ClassA *obj2 = obj1; //retain count = 1 [obj2 retain]; //retain count = 2 [obj1 hello]; //輸出hello //對于obj1,無需調用(實際上不能調用)release [obj2 hello]; //輸出hello [obj2 release]; //retain count = 2-1 = 1

這里有個有趣的問題,retain count不是1么,還不能銷毀呀,什么時候才能銷毀呢?

所以我們得了解一下autorelease pool的原理機制。

1)autorelease pool不是天生的,需要手動創立。只不過在新建一個iphone項目時,xcode會自動幫你寫好。autorelease pool的真名是NSAutoreleasePool。

  

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

?

2)NSAutoreleasePool內部包含一個數組(NSMutableArray),用來保存聲明為autorelease的所有對象。如果一個對象聲明為autorelease,系統所做的工作就是把這個對象加入到這個數組中去。

ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1,把此對象加入autorelease pool中

3) ??NSAutoreleasePool自身在銷毀的時候,會遍歷一遍這個數組,release數組中的每個成員。如果此時數組中成員的retain count為1,那么release之后,retain count為0,對象正式被銷毀。如果此時數組中成員的retain count大于1,那么release之后,retain count大于0,此對象依然沒有被銷毀,內存泄露。

?

那是不是有了自動釋放池autorelease pool就萬無一失了,其實不然

默認只有一個自動釋放池

int main (int argc, const char *argv[]) { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init];// do something[pool release]; return (0); } // main

所有標記為autorelease的對象在這個pool內被銷毀,但是如果這個自動釋放池里面含有大量autorelease的對象,還是容易造成內存不足的情況,比如說:

int main (int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int i, j; for (i = 0; i < 100; i++ ) {for (j = 0; j < 100000; j++ )[NSString stringWithFormat:@"1234567890"];//產生的對象是autorelease的。 } [pool release]; return (0); } // main

這種情況,大量內存被占用,只有poll銷毀的時候,那些聲明為autorelease對象才被銷毀,這對于ios程序來說并不樂觀,iphone內存本身有限,那有沒有更好的解決辦法,所以我們可以用autorelease嵌套機制來控制。

??Objective-C程序中可以嵌套創建多個autorelease pool。在需要大量創建局部變量的時候,可以創建內嵌的autorelease pool來及時釋放內存。

int main (int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int i, j; for (i = 0; i < 100; i++ ) {NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];for (j = 0; j < 100000; j++ )[NSString stringWithFormat:@"1234567890"];//產生的對象是autorelease的。[loopPool release]; } [pool release]; return (0); } // main

?

轉載于:https://www.cnblogs.com/yueyingsuixing/p/3457767.html

總結

以上是生活随笔為你收集整理的IOS面试_1.浅析内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。