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

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

內存管理2(主講MRR)

2019-11-14 18:31:03
字體:
來源:轉載
供稿:網友

內存管理2

我們討論過PRoperties 后,所有的內存管理系統都是通過控制所有對象的生命周期來減少內存的占用。iOS和OS X應用程序完成這些是通過對象擁有者來實現的,它保證了只要對象使用就會存在,但是不長。
這種對象擁有者的模式來自于引用計數系統,它會記錄對象現在被多少對象擁有,當你生命一個對象的擁有者,你要增加它的計數,而當你不用這個對象的時候,你需要減少這個計數。只要它的引用計數大于0,對象就一定會存在。但是一旦計數為0,操作系統就會被允許釋放它。

在過去,開發者通常通過調用一個被NSObject protocol定義的特殊的內存管理方法來控制對象的引用計數。這個方法叫做Manual Retain Release(MRR),也就是手動保持釋放。然而,到了Xcode4.2之后介紹了Automatic Reference Countin(ARC),就是自動引用釋放。ARC自動地插入了所有他們的方法。

如今的應用程序應該總是使用ARC,

因為它更加可靠而且使你專注于你的App特性而不是內存管理。
該文章主要解釋引用計數概念里面的MRR,然后討論一些特別需要關注的關于ARC的一些知識。

Manual Retain Release

在手動保持釋放環境中,持有和放棄每個對象的所有權是我們的工作。你實現這些需要調用一些特殊的內存相關方法,下面就是用到的方法以及簡短描述

方法行為
alloc創建一個對象并且聲明它的所有權
retian聲明一個存在對象的所有權
copy復制一個對象,然后聲明它的所有權
release放棄一個對象的所有權,然后立刻銷毀它
autorelease放棄對象的所有權,但是延遲銷毀。(最終也是銷毀)

手動的控制一個對象的所有權貌似看起來是一件令人害怕的任務,但是其實它非常容易。你要做的就是聲明任何你需要對象的所有權,當你不再使用的時候記得放棄所有權就行了。從實用的角度來看,意味著你必須平衡alloc,retain和copy的調用使用release或者autorelease再相同的對象上。
如果你忘記了release一個對象,那么它的潛在的內存將不會被釋放,這樣就會造成內存泄露。如果泄露嚴重就會導致程序崩潰。相反如果你調用release太多次數的話,會產生野指針(懸掛指針)。當你試圖訪問懸掛指針的時候,你就會請求一個無效的內存地址,這樣你的程序很有可能崩潰。

下面來解釋一樣如何通過合理的使用上面提到的方法來避免內存泄露和懸掛指針。

允許MRR

內存管理(1)中我們介紹過了,就不在介紹了。

alloc方法

我們已經知道使用alloc創建一個對象。但是,它不僅僅是給對象分配了內存,它也設置它的引用計數為1.這也合理,因為我們如果不想持有這個對象(持有一小會兒也算)那么我們就沒有必要去創建對象。

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {    @autoreleasepool {        NSMutableArray *mutableArray = [[NSMutableArray alloc] init];        [mutableArray addObject:@"Scott"];        NSLog(@"%@",mutableArray);    }    return 0;}

上述帶么我們肯定很熟悉,就是實例化一個可變數組,添加一個value,然后打印它的內容。從內存管理的角度來看,我們現在有一個mutableArr對象,這就意味著后面我們必須在某個地方要release它。
但是,在代碼中我們沒有釋放它,我們的代碼現在就有一個內存泄露。我們可以通過Product-->Analyze測試出來。結果如下:

這就有一個問題,它可以在上圖中看到(main.m)。
這是一個很小的對象,因此泄露不太致命。然而,如果他一次又一次地發生(例如在一個循環中或者用戶一直點擊一個按鈕),那么這個程序就會最終用完內存,然后崩潰。

release方法

該方法通過放棄對象的所有權來減少引用計數。因此,我們可以解決內存泄露問題通過在NSLog()后面添加下面的代碼:

[mutableArray release];

現在我們的alloc和release就平衡了,靜態分析就不會報出任何錯誤。典型的,你將會想放棄對象的所有權在同樣的方法之后。

過早釋放會造成懸掛指針。例如,在NSLog()前面去調用release方法。因為release會立刻釋放占用的內存,mutableArray變量在NSLog()里面就指向了一塊不可用的內存,然后你的程序就會崩潰:EXC_BAD_access error code 當你想運行的時候。(最新的Xcode現在直接打印出來空,而沒有提示錯誤。)

因此,不要在還在使用一個對象的時候而去釋放它。

retain方法

我們現在新建一個對象CarStore。
CarStore.h

#import <Foundation/Foundation.h>@interface CarStore : NSObject- (NSMutableArray *)inventArr;- (void)setInventArr:(NSMutableArray *)newInventArr;@end

CarStore.m

#import "CarStore.h"@implementation CarStore{    NSMutableArray *_inventArr;}- (NSMutableArray *)inventArr {    return _inventArr;}- (void)setInventArr:(NSMutableArray *)newInventArr {    _inventArr = newInventArr;}@end

然后我們在main.m中進行如下操作:

#import <Foundation/Foundation.h>#import "CarStore.h"int main(int argc, const char * argv[]) {    @autoreleasepool {        NSMutableArray *mutableArray = [[NSMutableArray alloc] init];        [mutableArray addObject:@"Scott"];                CarStore *superStore = [[CarStore alloc] init];        [superStore setInventArr:mutableArray];                 [mutableArray release];        NSLog(@"%@",[superStore inventArr]);           }    return 0;}

此時我們會發現里面是沒有數據的。因為此時inventArr就是一個懸掛指針,因為對象已經被released了在main.m中?,F在,superstore對象有個弱引用array.為了實現強引用,CarStore需要聲明數組所有權:

- (void)setInventArr:(NSMutableArray *)newInventArr {    _inventArr = [newInventArr retain];}

這樣就確保了inventArr沒有被釋放當superstore正在使用他的時候??梢钥匆幌拢簉etain方法返回是對象的本身,這就是我們執行retain和指派任務在一行。
然而這又造成了另一個問題:retain調用沒有平衡release,因此會產生另一個內存泄露。當我們傳遞過數組之后,我們不能訪問老得數值,這就意味著我們將不會使用它,為了解決這個問題,我們需要調用release去釋放老值: //不太理解,依然會報內存泄露

- (void)setInventArr:(NSMutableArray *)newInventArr {    if (_inventArr==newInventArr) {        return;    }    NSMutableArray *oldValue = _inventArr;    _inventArr = [newInventArr retain];    [oldValue release];}

這就是tetain和strong屬性做的事情,使用property將會更方便。

由此可知alloc和retain必須和release平衡,確保內存最終被釋放。

copy方法

另一種保留是復制的方法,它創建了一個新實列對象和增加了引用計數,保留最初的影響。因此,如果你想復制mutalbeArr,而不是指向可變的,你可以修改setInventory方法如下:

- (void)setInventArr:(NSMutableArray *)newInventArr {    if (_inventArr==newInventArr) {        return;    }    NSMutableArray *oldValue = _inventArr;    _inventArr = [newInventArr copy];    [oldValue release];}

一些類支持多重復制方法(例如多重init方法)。任何copy的對象具有相同的行為。

autorelease方法

就像release一樣,autorelease方法放棄對象的所有權,但是不是立刻銷毀對象,它延遲釋放內存。這樣允許你當你應該釋放對象的時候釋放。
例如,考慮一下一個簡單的工廠方法:

	+ (CarStore *)carStore;

從技術上講,是carStore方法對對象的釋放負責,因為調用者不知道該方法擁有返回對象。因此,它應該實現返回一個自動釋放的對象,就像下邊:

+ (CarStore *)carStore {    CarStore *newStore = [[CarStore alloc] init];    return [newStore autorelease];}

那么這個對象就放棄了所有權,延遲釋放,,然后會調用正常的release方法。這就是為什么main()

它確保當程序結束運行的時候,自動釋放對象被銷毀。

在ARC之前,它是一個很方便的方式,因為它讓你創建對象但是不用擔心在后面什么時候哪里去調用release。
如果你改變superstore的創建方式,使用下邊的:

//        CarStore *superStore = [[CarStore alloc] init];        CarStore *superStore = [CarStore carStore];        

實際上,你不允許釋放這個superstore實例了現在,因為你不再擁有它--而是carStore工程方法擁有它。一定不要去release一個autorelease對象,否則你會產生懸掛指針,甚至使程序崩潰。

dealloc方法

該方法和init方法相同。它被合理的使用在對象銷毀之前。給你個機會來清理任何內部的對象們。這個方法通過runtime自動調用------

你不應該去自己調用dealloc。

在MRR環境中,最常見的你需要做的就是使用dealloc方法去釋放一個實例變量存儲的對象。想想我們剛才的CarStore當一個實例dealloc時發生了什么:它的_inventArr(被setter保持著的)從來沒有機會被釋放。這是另一種形式的內存泄露,為了解決這些,我們要做的就是添加一個dealloc方法到CarStore.m中:

- (void)dealloc {    [_inventArr release];    [super dealloc];}

你必須要調用super dealloc去保證父類中的實例變量在合適的時間去釋放。為了讓dealloc簡單,我們不應該在dealloc里面去進行邏輯處理。

MRR總結:

總之,關鍵是處理好alloc,retain和copay 和release活著autorelease之間的平衡,否則你就會遇到懸掛指針活著內存泄露在你的程序中。

在真實地路上,上面好多代碼都是廢棄的。但是通過上面可以讓你更好的理解ARC編譯原理。

Automatic Reference Counting(自動引用計數,ARC)

現在,你已經了解了MMR,現在你可以忘記他們了。ARC和MRR的工作方式一樣,但是它自動為你插入合適的內存管理方法。這對于OC開發者是很好地處理。因為我們可以把精力放在應用程序需要做什么而不是如何做。

ARC中人為錯誤的內存管理幾乎不存在,所以使用他的唯一理由可能就是使用過去的第三方代碼庫。(然而,ARC大部分情況下向后兼容MRR程序)。下面就是介紹MRR和ARC之間的切換。

允許ARC

Project--->Build Settings--->搜索garbage,找到Objective-C Automatic Reference Counting設置為YES即可。

沒有更多的內存方法

ARC通過分析代碼每個對象的理想的生存時間應該是多來工作,然后自動的插入必要的retain和release方法。該方式需要完全控制整個程序中對象的所有權,

這就意味著你不允許調用retain,release或者autorelease

唯一你可能見到的在ARC中的內存相關方法就是alloc和copy。

新的屬性

,你應該使用strong來代替retain,使用weak來代替assign。這些已經在properties 討論過了。

ARC中的dealloc方法

dealloc在ARC中有一點不同,你不要release實例變量在dealloc方法中---ARC已經為你實現了。另外,父類的dealloc是自動調用,你也不需要[super dealloc]
但是有一種例外,如果你使用的低層次的內存構造函數,就像malloc(),那樣的話,你仍然需要調用free在dealloc中去避免內存泄露。

總結

ARC中你唯一要關系的就是循環引用。
你應該明白了所有你應該知道的關于OC的內存管理。

附:


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日本亚洲视频| 国产精品久久久久不卡| 91高清免费在线观看| 久久影视电视剧凤归四时歌| 粗暴蹂躏中文一区二区三区| 中文字幕日韩专区| 欧美亚洲第一页| 国产欧美 在线欧美| 日韩二区三区在线| 日韩专区在线播放| 亚洲激情在线观看| 亚洲人av在线影院| 成人黄色短视频在线观看| 久久免费精品日本久久中文字幕| 精品一区二区三区四区在线| 色偷偷91综合久久噜噜| 日韩男女性生活视频| 欧美电影院免费观看| 亚洲综合色激情五月| 亚洲一区二区三区视频| 亚洲激情视频网站| 中日韩午夜理伦电影免费| 亚洲精品www| 国产亚洲精品久久久优势| 日韩欧美高清在线视频| 国产精品福利在线观看| 国产91精品最新在线播放| 国产女人精品视频| 久久久最新网址| 久久久国产精彩视频美女艺术照福利| 久久久爽爽爽美女图片| 日韩av在线免费播放| 亚洲综合在线播放| 久久国内精品一国内精品| 亚洲一区美女视频在线观看免费| 久久艳片www.17c.com| 国产精品久久久久影院日本| 亚洲老头同性xxxxx| 国产精品激情av在线播放| 亚洲欧美日韩一区在线| 亚洲女人天堂网| 不用播放器成人网| 亚洲精品自拍偷拍| 国产精品亚洲网站| 欧美性jizz18性欧美| 日韩高清人体午夜| 色偷偷av一区二区三区乱| 91超碰caoporn97人人| 97在线免费观看| 热re91久久精品国99热蜜臀| 欧美国产日韩免费| 精品无人国产偷自产在线| 亚洲精品wwwww| 欧美成人sm免费视频| 欧美最猛黑人xxxx黑人猛叫黄| 日韩av色在线| 黑人巨大精品欧美一区二区三区| 国产午夜精品全部视频在线播放| 欧美与欧洲交xxxx免费观看| 亚洲色图15p| 欧美一级片一区| 亚洲一级片在线看| 热99在线视频| 国产成人精彩在线视频九色| 国产成人在线一区二区| 国产一区二区三区四区福利| 91美女片黄在线观看游戏| 日本伊人精品一区二区三区介绍| 亚洲日韩欧美视频一区| 日韩精品中文在线观看| 欧美日韩在线免费观看| 日韩在线观看精品| 在线观看欧美日韩| 亚洲香蕉成人av网站在线观看| 亚洲国产成人精品电影| 一本一道久久a久久精品逆3p| 亚洲成年人在线播放| 亚洲欧美日韩视频一区| 欧美激情一区二区久久久| 亚州av一区二区| 午夜精品理论片| 少妇高潮久久久久久潘金莲| 亚洲欧美日韩图片| 日本伊人精品一区二区三区介绍| 精品综合久久久久久97| 国产精品视频公开费视频| 精品久久久久久久久久| 奇米影视亚洲狠狠色| 欧美精品videosex性欧美| 欧美日韩另类在线| 成人国产亚洲精品a区天堂华泰| 91欧美激情另类亚洲| 国产精品电影在线观看| 992tv在线成人免费观看| 日韩av网站在线| 午夜精品一区二区三区在线视频| 欧美日韩第一视频| 久久视频免费观看| 亚洲精品视频免费在线观看| 欧美成人精品三级在线观看| 欧美视频一二三| 国产精品稀缺呦系列在线| 成人免费看吃奶视频网站| 亚洲天堂第一页| 国产精品白丝av嫩草影院| 美女久久久久久久| 欧美成人一区二区三区电影| 国产ts人妖一区二区三区| 国产欧美一区二区三区在线| 亚洲天堂成人在线| 欧美成人免费视频| 欧美精品18videos性欧| 超碰91人人草人人干| 日韩极品精品视频免费观看| 在线成人激情视频| 国产一区二区在线免费| 亚洲精品久久久久久久久久久久| 亚洲精美色品网站| 日韩经典中文字幕| 日韩在线视频观看正片免费网站| 日韩av男人的天堂| 中文字幕亚洲精品| 中文字幕久精品免费视频| 深夜福利一区二区| 国产精品久久久久久久久久99| 中文字幕不卡av| 丝袜亚洲另类欧美重口| 亚洲欧美日韩区| 日韩亚洲欧美成人| 欧美性猛交xxxx乱大交极品| 亚洲欧美国内爽妇网| 亚洲精品白浆高清久久久久久| 久久成人这里只有精品| 日韩69视频在线观看| 日韩在线中文字| 欧美主播福利视频| 欧美成人激情图片网| 一本色道久久88亚洲综合88| 国产精品h片在线播放| 国产精品视频yy9099| 亚洲精品天天看| 成人天堂噜噜噜| 在线视频一区二区| 国产不卡在线观看| 久久福利视频网| 国产精品久久久久久久天堂| 亚洲春色另类小说| 91精品视频免费| 日韩综合中文字幕| 91久久久久久久久久久| 亚洲精品黄网在线观看| 日本韩国在线不卡| 日本精品免费观看| 色妞色视频一区二区三区四区| 欧美激情视频一区二区三区不卡| 9.1国产丝袜在线观看| 92版电视剧仙鹤神针在线观看| 亚洲电影成人av99爱色| 在线电影欧美日韩一区二区私密| 成人国产精品久久久久久亚洲| 92国产精品视频| 深夜福利亚洲导航| 久久久成人av| 成人在线观看视频网站|