亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Objective-c 內存溢出問題經驗匯總

2019-11-09 14:08:57
字體:
來源:轉載
供稿:網友
OS平臺的內存使用引用計數的機制,并且引入了半自動釋放機制;這種使用上的多樣性,導致開發者在內存使用上非常容易出現內存泄漏和內存莫名的增 長情況; 本文會介紹iOS平臺的內存使用原則與使用陷阱; 深度剖析autorelease機制;低內存報警后的處理流程;并結合自身實例介紹內存暴增的問題追查記錄以及相關工具的使用情況;

iOS平臺內存常見問題

作為iOS平臺的開發者,是否曾經為內存問題而苦惱過?內存莫名的持續增長,程序莫名的 crash,難以發現的內存泄漏,這些都是iOS平臺內存相關的常見問題;本文將會詳細介紹iOS平臺的內存管理機制,autorelease機制和內存 的使用陷阱,這些將會解決iOS平臺內存上的大部分問題,提高了程序的穩定性;

1 iOS平臺內存管理介紹

iOS平臺的內存管理采用引用計數的機制;當創建一個對象時使用alloc或者allWithZone方法時,引用計數就會+1;當釋放對象使用release方法時,引用計數就是-1; 這就意味著每一個對象都會跟蹤有多少其他對象引用它,一旦引用計數為0,該對象的內存就會被釋放掉;另外,iOS也提供了一種延時釋放的機制 AutoRelease,以這種方式申請的內存,開發者無需手動釋放,系統會在某一時機釋放該內存; 由于iOS平臺的這種內存管理的多樣性,導致開發者在內存使用上很容易出現內存泄漏或者程序莫名崩潰的情況,本文會詳細介紹iOS平臺內存的使用規范與技 巧以及如何利用工具避免或者發現問題;

2 iOS平臺內存使用原則

2.1 對象的所有權與銷毀

2.1.1 誰創建,誰釋放;

如果是以alloc,new或者copy,mutableCopy創建的對象,則必須調用release或者autorelease方法釋放內存;

如果沒有釋放,則導致內存泄漏!

2.1.2 誰retain,誰釋放;

如果對一個對象發送 retain消息,其引用計數會+1,則使用完必須發送release或者autorelease方法釋放內存或恢復引用計數;

如果沒有釋放,則導致內存泄漏!

2.1.3 沒創建且沒retain,別釋放;

不要釋放那些不是自己alloc或者retain的對象,否則程序會crash;

不要釋放autorelease的對象,否則程序會crash;

2.2 對象的深拷貝與淺拷貝

一般來說,復制一個對象包括創建一個新的實例,并以原始對象中的值初始化這個新的實例。 復制非指針型實例變量的值很簡單,比如布爾,整數和浮點數。復制指 針型實例變量有兩種方法。一種方法稱為淺拷貝,即將原始對象的指針值復制到副本中。因此,原始對象和副本共享引用數據。另一種方法稱為深拷貝,即復制指針 所引用的數據,并將其賦給副本的實例變量。

2.2.1 深拷貝

深拷貝的流程是 先創建一個新的對象且引用計數為1,并用舊對象的值初始化這個新對象;

ClassA* objA = [[ClassA alloc] init];

ClassA* objB = [objA copy];

objB是一個新對象,引用計數為1,且objB的數據等同objA的數據;

注意: objB需要釋放,否則會引起內存泄漏!

2.2.2 淺拷貝

淺拷貝的流程是,無需引入新的對象,把原有對象的引用計數+1即可

ClassA* objA = [[ClassA alloc] init];

ClassA* objB = [objA retain];

注意: objB需要釋放,恢復objA的引用計數,否則會引起內存泄漏!

2.3對象的存取方法2.3.1 屬性聲明和實現

變量聲明的常用屬性類型包括readonly,assign,retain和copy;且系統會自動為聲明了屬性的變量生成set和get函數;

readonly屬性: 只能讀,不能寫;

assign屬性: 是默認屬性,直接賦值,沒有任何保留與釋放問題;

retain屬性: 會增加原有對象的引用計數并且在賦值前會釋放原有對象,然后在進行賦值;

copy屬性:  會復制原有對象,并在賦值前釋放原有對象,然后在進行賦值;

2.3.2 使用屬性聲明可能帶來的隱患

當一個非指針變量使用retain(或者copy)這個屬性時,盡量不要顯性的release這個變量;直接給這個變量置空即可;否則容易產生過度釋放,導致程序crash; 例如:

ClassA類的strName是NSString* 類型的變量且聲明的屬性為retain;

ClassA.strName = nil;  /* 釋放原有對象且對此對象賦值為空 */

[ClassA.strName release]; /* strName內存可能已經被釋放過了,將導致程序crash */

Assign這個屬性一般是非指針變量(布爾類型,整形等)時用這個類型;屬于直接賦值型,不需要考慮內存的保留與釋放;

如果一個指針類型的變量使用assign類型的屬性,有可能引用已經釋放的變量;導致程序crash; 例如:

ClassB* obj =[[[ClassB alloc] init] autorelease];

……

ClassA.strName = obj; /* strName 指向obj的內存地址*/

后續在使用ClassA.strName的時候, 因為obj是autorelease的,可能obj的內存已經被回收;導致引用無效內存,程序crash;

3iOS平臺AutoRelease機制3.1 自動釋放池的常見問題

大家在開發iOS程序的時候,是否遇到過在列表滑動的情況內存莫名的增長,頻繁訪問圖片的時候內存莫名的增長,頻繁的打開和關閉數據庫的時候內存莫名的增長…… 這些都是拜iOS的autorelease機制所賜;具體分析如下:

1: 滑動列表的時候,內存出現莫名的增長,原因可能有如下可能:

1:沒有使用UITableView的reuse機制; 導致每顯示一個cell都用autorelease的方式重新alloc一次; 導致cell的內存不斷的增加;

2:每個cell會顯示一個單獨的UIView, 在UIView發生內存泄漏,導致cell的內存不斷增長;

2: 頻繁訪問圖片的時候,內存莫名的增長;

頻繁的訪問網絡圖片,導致iOS內部API,會不斷的分配autorelease方式的buffer來處理圖片的解碼與顯示; 利用圖片cache可以緩解一下此問題;

3: 頻繁打開和關閉SQLite,導致內存不斷的增長;

在進行SQLite頻繁打開和關閉操作,而且讀寫的數據buffer較大,那么 SQLite在每次打開與關閉的時候,都會利用autorelease的方式分配51K的內存; 如果訪問次數很多,內存馬上就會頂到幾十兆,甚至上百兆! 所以針對頻繁的讀寫數據庫且數據buffer較大的情況, 可以設置SQLite的長連接方式;避免頻繁的打開和關閉數據庫;

3.2 自動釋放池的概念

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

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

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

3.3 自動釋放池的作用域與嵌套

AutoreleasePool是可以嵌套使用的!

池是被嵌套的,嵌套的結果是個棧,同一線程只有當前棧頂pool實例是可用的:

當短生命周期內,比如一個循環中,會產生大量的臨時內存,可以創建一個臨時的autorelease pool,這樣可以達到快速回收內存的目的;

3.4 自動施放池的手動創建與自動創建

3.4.1 需要手動創建自動釋放池

●如果你正在編寫一個不是基于application Kit的程序,比如命令行工具,則沒有對自動釋放池的內置支持;你必須自己創建它們。

●如果你生成了一個從屬線程,則一旦該線程開始執行,你必須立即創建你自己的自動釋放池;否則,你將會泄漏對象。

●如果你編寫了一個循環,其中創建了許多臨時對象,你可以在循環內部創建一個自動釋放池,以便在下次迭代之前銷毀這些對象。這可以幫助減少應用程序的最大內存占用量。

3.4.2 系統自動創建自動釋放池

Application Kit會在一個事件周期(或事件循環迭代)的開端—比如鼠標按下事件—自動創建一個自動釋放池,并且在事件周期的結尾釋放它.

4 iOS平臺內存使用陷阱

4.1 重復釋放

在前文已經提到,不要釋放不是自己創建的對象;

釋放自己的autorelease對象,app會crash;

釋放系統的autorelease對象,app會crash;

4.2 循環引用

循環引用,容易產生野引用,內存無法回收,最終導致內存泄漏!可以通過弱引用的方式來打破循環引用鏈;所謂的弱引用就是不需要retain,直接賦值的方式,這樣的話,可以避免循環引用的問題,但是需要注意的是,避免重復釋放的問題;

5 iOS平臺內存報警機制

由于iOS平臺的內存管理機制,不支持虛擬內存,所以在內存不足的情況,不會去Ram上 創建虛擬內存;所以一旦出現內存不足的情況,iOS平臺會通知所有已經運行的app,不論是前臺app還是后臺掛起的app,都會收到 memory warning的notice;一旦app收到memory warning的notice,就應該回收占用內存較大的變量;

5.1 內存報警處理流程

1: app收到系統發過來的memory warning的notice;

2: app釋放占用較大的內存;

3: 系統回收此app所創建的autorelease的對象;

4: app返回到已經打開的頁面時,系統重新調用viewdidload方法,view重新加載頁面數據;重新顯示;

5.2 內存報警測試方法

在Simulate上可以模擬低內存報警消息;

iOS模擬器 -> 硬件 -> 模擬內存警告;

開發者可以在模擬器上來模擬手機上的低內存報警情況,可以避免由于低內存報警引出的app的莫名crash問題;

6 iOS平臺內存檢查工具

6.1 編譯和分析工具Analyze

iOS的分析工具可以發現編譯中的warning,內存泄漏隱患,甚至還可以檢查出logic上的問題;所以在自測階段一定要解決Analyze發現的問題,可以避免出現嚴重的bug;

內存泄漏隱患提示:

Potential Leak of an object allocated on line ……

數據賦值隱患提示:

The left Operand of …… is a garbage value;

對象引用隱患提示:

Reference-Counted object is used after it is released;

以上提示均比較嚴重,可能會引起嚴重問題,需要開發者密切關注!

6.2內存檢測工具

6.2.1 內存泄漏檢測工具—Leak

Leak工具可以很容易的統計所有內存泄漏的點,而且還可以顯示在那個文件,哪行代碼有 內存泄漏,這樣定位問題比較容易,也比較方面;但是Leak在統計內存泄漏的時候會把autorelease方式的內存也統計進來; 所以我們在查找內存泄漏情況的時候,可以autorelease的情況忽略掉;

Leak工具:

通過Leak工具可以很快發現代碼中的內存泄漏,通過工具也可以很快找到發生內存泄漏的代碼段:

6.2.2 內存猛增檢測工具—Allocations

Allocations工具可以很容易的列出所有分配內存的點,這樣我們可以按照分配內存大小來進行排序, 這樣可以很容易的發現哪些點分配的內存最多,而且是持續分配,這樣我們來針對性的分析這些持續分配較大內存的地方;

此工具會顯示出所有申請內存的地方,并統計申請的次數和大?。?從這個列表中可以找出內存申請次數最多且申請內存最大的語句;從而分析出哪些地方使用的內存最多,進而可以優化和改進。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久最新资源网| 精品国产乱码久久久久久虫虫漫画| 91精品国产91| 2023亚洲男人天堂| 麻豆一区二区在线观看| 在线日韩av观看| 亚洲国产精品悠悠久久琪琪| 成人久久久久爱| 黄色成人在线播放| 91国产精品91| 91欧美精品成人综合在线观看| 欧美第一页在线| 亚洲精品短视频| 高跟丝袜一区二区三区| 久久国产精品影视| 久久在线视频在线| 亚洲欧美在线x视频| 中文字幕成人精品久久不卡| 国产精品一区二区三区久久久| 亚洲精品成人久久久| 国产精品免费看久久久香蕉| 日韩电影中文 亚洲精品乱码| 久久99久久99精品免观看粉嫩| 91精品在线观| 欧美日韩人人澡狠狠躁视频| 欧美日韩福利视频| 深夜精品寂寞黄网站在线观看| 国产精品99免视看9| 精品人伦一区二区三区蜜桃网站| 亚洲电影中文字幕| 久久久亚洲精选| 欧美精品在线极品| 亚洲xxxx视频| 久久视频在线免费观看| 免费91麻豆精品国产自产在线观看| 国产精品27p| 欧美成人免费一级人片100| 日韩精品免费看| 黑人巨大精品欧美一区免费视频| www.亚洲人.com| 91免费观看网站| 国产日韩在线一区| 久久资源免费视频| 国产精品jizz在线观看麻豆| 91中文精品字幕在线视频| 91豆花精品一区| 91精品国产综合久久香蕉的用户体验| 日韩av在线一区| 国产精品爽黄69天堂a| 久久香蕉精品香蕉| 国产极品精品在线观看| 欧美激情第6页| 在线亚洲午夜片av大片| 疯狂蹂躏欧美一区二区精品| 26uuu另类亚洲欧美日本一| 热久久免费视频精品| www.日韩系列| 97人洗澡人人免费公开视频碰碰碰| 国自在线精品视频| 成人xvideos免费视频| 国产成人精品在线| 欧美日韩国产精品一区二区不卡中文| 国内伊人久久久久久网站视频| 国产精品18久久久久久麻辣| 精品亚洲夜色av98在线观看| 黑人巨大精品欧美一区二区一视频| 国产精品一二区| 亚洲国产天堂久久国产91| 日韩亚洲国产中文字幕| 毛片精品免费在线观看| 国产在线拍偷自揄拍精品| 亚洲精品国产福利| 国产精品看片资源| 精品丝袜一区二区三区| 97在线精品国自产拍中文| 欧美丝袜一区二区三区| 91精品久久久久久久久中文字幕| 欧美主播福利视频| 久久久久久有精品国产| 日本精品视频网站| 久久久久一本一区二区青青蜜月| 亚洲日本中文字幕免费在线不卡| 亚洲丁香婷深爱综合| 91久久在线播放| 国产精品6699| 欧美最近摘花xxxx摘花| 91久久久久久久一区二区| 亚洲欧美日韩直播| 亚洲xxxxx电影| 久久精品视频在线观看| 欧美在线一区二区视频| 日韩暖暖在线视频| 欧美极品欧美精品欧美视频| 国产一区二区日韩| 欧美性生交xxxxx久久久| 欧洲一区二区视频| 欧美日韩国产在线播放| 国产区精品视频| 成人黄在线观看| 欧美视频在线观看免费| 久久久久久欧美| 成人97在线观看视频| 91精品国产高清自在线| 国产精品久久久久久久美男| 91色中文字幕| 久久亚洲春色中文字幕| 91香蕉嫩草影院入口| 日韩精品久久久久| 狠狠色狠狠色综合日日五| 精品久久久免费| 欧美另类69精品久久久久9999| 日韩av电影免费观看高清| 欧美亚洲日本网站| 成人免费在线网址| 久久久久久久久久久亚洲| 大桥未久av一区二区三区| 欧美日韩aaaa| 国产91在线播放九色快色| 亚洲精品国精品久久99热| 国色天香2019中文字幕在线观看| 精品自在线视频| 欧美日韩一区二区免费在线观看| 国产精品丝袜久久久久久不卡| 久久成人精品电影| 国产精品海角社区在线观看| 国产日韩在线精品av| 91久久嫩草影院一区二区| 亚洲精品一区久久久久久| 日韩黄色av网站| 全色精品综合影院| 国产一区二区在线播放| 神马国产精品影院av| 欧美成人精品一区二区三区| 欧美一级免费看| 国产男女猛烈无遮挡91| 亚洲国产中文字幕久久网| 欧美黑人狂野猛交老妇| 国产黑人绿帽在线第一区| 久久精品99久久久久久久久| 久久人人爽人人| 国产精自产拍久久久久久蜜| 2025国产精品视频| 欧美影院久久久| 欧美一二三视频| 欧美在线激情视频| 欧美另类69精品久久久久9999| 国产精品 欧美在线| 亚洲午夜久久久久久久| 国产精品永久免费视频| 亚洲一区二区三| 国产精品福利在线| 高跟丝袜欧美一区| 日韩激情视频在线播放| 伊人亚洲福利一区二区三区| 亚洲丁香久久久| 国产激情久久久久| 2019av中文字幕| 欧美日韩国产专区| 国语自产精品视频在线看一大j8| 日韩欧美亚洲成人| 视频在线一区二区| 国产亚洲欧美一区| 国产精品视频一区二区三区四| 久久国产精品久久久久|