autoreleasepool釋放時機(jī)

最開始只是想試一試寫在方法內(nèi)部的局部變量釋放時經(jīng)不經(jīng)過autoreleasepool罪治。

例如丽声,下圖這樣的代碼。

xxx.png

為了不影響對象本身的引用計(jì)數(shù)影響它的銷毀過程觉义,使用一個weak指針雁社,不出所料的,打印出來了如下結(jié)果

001.png

但是這個實(shí)驗(yàn)如果換成NSString得到的則是完全不一樣的結(jié)果晒骇。

如下代碼

002.png

打印出來的結(jié)果卻是:

003.png

這個看上去也很好似乎也很好理解霉撵,NSString初始化的時候是存放在常量區(qū)的,所以沒有釋放嘛洪囤。

深入研究

為了觀察對象的釋放過程徒坡,我們在str賦值的地方加一個斷點(diǎn)

breakpoint.png

走到該斷點(diǎn)的時候通過lldb命令watchpoint set variable str來觀察,可以看到str由0x0000000000000000變成0x00000001056b3250瘤缩。

04.png

然后一路點(diǎn)擊Continue program execution喇完,發(fā)現(xiàn)str會變成0x0000000000000000,控制臺只打印了一次str的值,也就是說viewwillappear還沒有執(zhí)行剥啤,這點(diǎn)跟雷大博客(Objective-C Autorelease Pool 的實(shí)現(xiàn)原理)中的略不一樣锦溪,我猜是apple改了。

05.png

然后看左側(cè)的方法調(diào)用棧府怯,會發(fā)現(xiàn)這個過程經(jīng)過了objc_store,AutoreleasePoolPage::pop(void *)等函數(shù)通過autoreleasepool釋放了】陶铮現(xiàn)在修改一下log語句。

06.png

看了幾個大神之前的博客牺丙,大都還打印了retainCount,但是今天這里研究的是arc坏逢,就不打印retainCount了。

執(zhí)行如下代碼:

074.png

得到打印結(jié)果:

066.png

可以看到這里其實(shí)是有三種String的,而references指向了cstr,此時在viewWillAppear和viewDidAppear里打印references得到的則是null是整。

三種String

  • NSCFConstantString: 字符串常量肖揣,放在常量區(qū),對其retain或者release不影響它的引用計(jì)數(shù)浮入,程序結(jié)束后釋放龙优。用字面量語法創(chuàng)建出來的string就是這種,所以在出了viewDidLoad方法以后在其他地方也能打印出值事秀,壓根就沒釋放彤断。
077.png
  • NSTaggedPointerString: Tagged Point,標(biāo)簽指針易迹,蘋果在64位環(huán)境下對NSString和NSNumber做的一些優(yōu)化宰衙,簡單來說就是把對象的內(nèi)容存放在了指針里,這樣就不需要在堆內(nèi)存里在開辟一塊空間存放對象了睹欲,一般用來優(yōu)化長度較小的內(nèi)容供炼。關(guān)于標(biāo)簽指針的內(nèi)容可以參考唐巧的介紹:深入理解Tagged Pointer

對于NSString,當(dāng)非字面量的數(shù)字窘疮,英文字母字符串的長度小于等于9的時候會自動成為NSTaggedPointerString類型袋哼。代碼中的bstr如果再加一位或者有中文在里面就是變成NSCFString。而NSTaggedPointerString也是不會釋放的闸衫,它的內(nèi)容就在本身的指針里涛贯,又沒有對象釋放個啥啊。所以如果把references的賦值代碼改為

08.png

在viewWillAppear和viewDidAppear中也是能打印出值來的蔚出。

NSCFString: 這種string就和普通的對象很像了弟翘,儲存在堆上,有正常的引用計(jì)數(shù)骄酗,需要程序員分配釋放衅胀。所以references = cstr時,會打印出null酥筝,cstr出了方法作用域在runloop結(jié)束時就被autoreleasepool釋放了滚躯。

stringWithFormat

到這里還是有問題

09.png

根據(jù)以上說法,當(dāng)string超過10位數(shù)時嘿歌,bstr和cstr都是NSCFString掸掏,可是兩種情況viewWillAppear和viewDidAppear在打印的結(jié)果不一樣。

bstr:

10.png

cstr:

11.png

根據(jù)太陽神黑幕背后的Autorelease中的說法宙帝,是因?yàn)関iewWillAppear和viewDidLoad在一個runloop中導(dǎo)致bstr在willappear中能打印出來值丧凤。如果真的是這樣那cstr講道理應(yīng)該也能打印出值來,文章最開始用NSObject做實(shí)驗(yàn)時在viewWillAppear時應(yīng)該也能打印出值來步脓。

所以其實(shí)并不是同一個runloop的問題愿待,問題出在stringWithFormat這個工廠方法上浩螺。

查資料得知以 alloc, copy, init,mutableCopy和new這些方法打頭的方法,返回的都是 retained return value仍侥,例如[[NSString alloc] initWithFormat:]要出,而其他的則是unretained return value,例如 [NSString stringWithFormat:]农渊。對于前者調(diào)用者是要負(fù)責(zé)釋放的患蹂,對于后者就不需要了。而且對于后者ARC會把對象的生命周期延長砸紊,確保調(diào)用者能拿到并且使用這個返回值传于,但是并不一定會使用 autorelease,在worst case 的情況下才可能會使用醉顽,因此調(diào)用者不能假設(shè)返回值真的就在 autorelease pool中沼溜。從性能的角度,這種做法也是可以理解的游添。如果我們能夠知道一個對象的生命周期最長應(yīng)該有多長系草,也就沒有必要使用 autorelease 了,直接使用 release 就可以否淤。如果很多對象都使用 autorelease 的話,也會導(dǎo)致整個 pool 在 drain 的時候性能下降棠隐。

也就是說通過工廠方法得到的string生命周期被延長了石抡,所以才會在viewWillAppear里依然可以打印出來。為了證實(shí)這一點(diǎn)助泽,我們換成array來做個實(shí)驗(yàn)啰扛。

14.png

第一種情況通過字面量創(chuàng)建array,打印臺輸出:

15.png

第二種情況通過工廠方法創(chuàng)建嗡贺,打印臺輸出:

16.png

可以看到通過工廠方法創(chuàng)建的array生命周期確實(shí)被延長了隐解。

總結(jié)

1.方法里的臨時變量是會通過autoreleasepool釋放的

2.NSCFString跟普通對象一樣是可以釋放的

3.NSString和NSArray的工廠方法可以延長對象的生命周期(同理,NSDictionary也是一樣的诫睬,有興趣的可以試一下)

——————————————轉(zhuǎn)載自http://www.cocoachina.com/ios/20170303/18829.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末煞茫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子摄凡,更是在濱河造成了極大的恐慌续徽,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亲澡,死亡現(xiàn)場離奇詭異钦扭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)床绪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門客情,熙熙樓的掌柜王于貴愁眉苦臉地迎上來其弊,“玉大人,你說我怎么就攤上這事膀斋∷蠓ィ” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵概页,是天一觀的道長籽御。 經(jīng)常有香客問我,道長惰匙,這世上最難降的妖魔是什么技掏? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮项鬼,結(jié)果婚禮上哑梳,老公的妹妹穿的比我還像新娘。我一直安慰自己绘盟,他們只是感情好鸠真,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著龄毡,像睡著了一般吠卷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沦零,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天祭隔,我揣著相機(jī)與錄音,去河邊找鬼路操。 笑死疾渴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的屯仗。 我是一名探鬼主播搞坝,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼魁袜!你這毒婦竟也來了桩撮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤峰弹,失蹤者是張志新(化名)和其女友劉穎距境,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垮卓,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡垫桂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粟按。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诬滩。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡霹粥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疼鸟,到底是詐尸還是另有隱情后控,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布空镜,位于F島的核電站浩淘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吴攒。R本人自食惡果不足惜张抄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望洼怔。 院中可真熱鬧署惯,春花似錦、人聲如沸镣隶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽安岂。三九已至轻猖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間域那,已是汗流浹背咙边。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琉雳,地道東北人样眠。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓友瘤,卻偏偏與公主長得像翠肘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辫秧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

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

  • 1束倍、[NSObject alloc]在創(chuàng)建完對象后,會讓該對象的retainCount+1盟戏,后續(xù)的init為初始化...
    naiyi閱讀 1,525評論 0 4
  • 目錄 autorelease的本質(zhì) autorelease對象什么時候釋放绪妹? autoreleasepool的工作...
    yanhooIT閱讀 5,150評論 5 35
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,093評論 1 32
  • 局部釋放池 創(chuàng)建一個新的自動釋放池的方法:ARC下: 這相當(dāng)于MRC下: 其中對象s會被加入到自動釋放池,當(dāng)ARC...
    thinkq閱讀 16,679評論 8 40
  • 內(nèi)存的引用 ??計(jì)算機(jī)是按地址訪問數(shù)據(jù)柿究,如果一塊內(nèi)存被使用邮旷,就必須讓外界知道它在哪兒,反過來講蝇摸,要訪問一個數(shù)據(jù)就必...
    吸血鬼de晚餐閱讀 2,022評論 0 5