iOS 12檢測內(nèi)存泄漏Analyze-Potential leak of an object stored into

IOS性能調(diào)優(yōu)系列:Analyze靜態(tài)分析

XCode已經(jīng)提供了非常強(qiáng)大的性能調(diào)優(yōu)工具坝冕,結(jié)合幾個(gè)第三方工具和一些技巧,進(jìn)行性能優(yōu)化非常簡單。

第一篇先寫寫最簡單的孩擂,Analyze靜態(tài)分析。

相信IOS開發(fā)者在App進(jìn)行Build或Archive時(shí)箱熬,會(huì)產(chǎn)生很多編譯警告类垦,這些警告是編譯時(shí)產(chǎn)生的,靜態(tài)分析的過程也類似城须,在XCode Product菜單下蚤认,點(diǎn)擊Analyze對App進(jìn)行靜態(tài)分析。


Analyze主要分析以下四種問題:

1糕伐、邏輯錯(cuò)誤:訪問空指針或未初始化的變量等砰琢;

2、內(nèi)存管理錯(cuò)誤:如內(nèi)存泄漏等;

3氯析、聲明錯(cuò)誤:從未使用過的變量亏较;

4、Api調(diào)用錯(cuò)誤:未包含使用的庫和框架掩缓。

Analyze內(nèi)存泄漏分析:

聲明錯(cuò)誤雪情、邏輯錯(cuò)誤、Api調(diào)用錯(cuò)誤基本在編譯時(shí)都會(huì)有警告你辣,Analyze的主要優(yōu)勢在于靜態(tài)分析內(nèi)存泄漏及代碼邏輯錯(cuò)誤巡通。

比如在開啟arc的環(huán)境下,輸入以下一段代碼:

ARC 和 非ARC 下 oc 對象 和 CF 對象的轉(zhuǎn)換

標(biāo)簽:objective-c內(nèi)存泄露CoreFundation

2014-03-11 11:301231人閱讀評論(0)收藏舉報(bào)

分類:

IOS開發(fā)(123)

版權(quán)聲明:本文為博主原創(chuàng)文章舍哄,未經(jīng)博主允許不得轉(zhuǎn)載宴凉。

在OC和FC之間進(jìn)行轉(zhuǎn)化的時(shí)候,主要是對象的歸屬問題表悬。共有兩種方式:

1弥锄、使用宏,可以標(biāo)識歸屬者從OC到CF蟆沫,還是從CF到OC籽暇。

[objc]view plaincopy

NS_INLINE?CFTypeRef?CFBridgingRetain(idX)?{

return(__bridge_retain?CFTypeRef)X;

}

NS_INLINEidCFBridgingRelease(CFTypeRef?X)?{

return(__bridge_transferid)X;

}

2、使用轉(zhuǎn)化符,如:__bridge饭庞,__bridge_transfer戒悠,__bridge_retained

__bridge:不涉及對象所有關(guān)系改變

__bridge_transfer:給予 ARC 所有權(quán)

__bridge_retained:解除 ARC 所有權(quán)

[objc]view plaincopy

idmy_id;

CFStringRef?my_cfref;

NSString???*a?=?(__bridge?NSString*)my_cfref;//?Noop?cast.

CFStringRef?b?=?(__bridge?CFStringRef)my_id;//?Noop?cast.

NSString???*c?=?(__bridge_transfer?NSString*)my_cfref;//?-1?on?the?CFRef

CFStringRef?d?=?(__bridge_retained?CFStringRef)my_id;//?returned?CFRef?is?+1

非ARC模式下:

[objc]view plaincopy

#pragma?mark?–?View?lifecycle

-?(void)viewDidLoad

{

[superviewDidLoad];

NSLog(@"=%@",?[selfescape:@"LIN986LIN"]);

}

-(NSString*)escape:(NSString*)text

{

return(NSString*)CFURLCreateStringByAddingPercentEscapes(NULL,?(__bridge?CFStringRef)text,NULL,CFSTR("!*’();:@&=+$,/?%#[]"),?CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

}

ARC模式下:

可以看到xcode自動(dòng)把上面函數(shù)轉(zhuǎn)化為:

[objc]view plaincopy

#pragma?mark?–?View?lifecycle

-?(void)viewDidLoad

{

[superviewDidLoad];

NSLog(@"=%@",?[selfescape:@"wangjun"]);

}

-(NSString*)escape:(NSString*)text

{

return(__bridge_transferNSString*)CFURLCreateStringByAddingPercentEscapes(NULL,?(__bridge?CFStringRef)text,NULL,CFSTR("!*’();:@&=+$,/?%#[]"),?CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

}

在arc中,CF和OC之間的轉(zhuǎn)化橋梁是 __bridge舟山,有兩種方式:

__bridge_transfer ?ARC接管管理內(nèi)存

__bridge_retained ?ARC釋放內(nèi)存管理

oc 到 CF 的轉(zhuǎn)化绸狐,需要把OC的內(nèi)存管理權(quán)釋放掉。

[objc]view plaincopy

NSString*str?=?[[NSStringalloc]initWithFormat:@"Welcome??,?%@!",name];

CFStringRef?strref?=?(__bridge_retained?CFStringRef)str;

//?do?something?with?strref

CFRelease(strref);

最后由CF進(jìn)行內(nèi)存釋放累盗。

上面代碼等同于:

[objc]view plaincopy

CFStringRef?strref?=?CFBridgingRetain(str);

//?do?something?with?strref

CFRelease(strref);

CF轉(zhuǎn)化為OC時(shí)寒矿,并且對象的所有者發(fā)生改變,則使用CFBridgingRelease()或__bridge_transfer 若债。

OC轉(zhuǎn)化為CF時(shí)符相,并且對象的所有者發(fā)生改變,則使用CFBridgingRetain()或__bridge_retained

當(dāng)一個(gè)類型轉(zhuǎn)化到另一種類型時(shí)拆座,但是對象所有者沒有發(fā)生改變主巍,則使用__bridge.

CF對象和OC對象混用可能出現(xiàn)的問題:

ARC模式下,自動(dòng)回收只針對Objective-C對象有效挪凑,對于Core Foundation對象還是需要我們手動(dòng)進(jìn)行釋放的孕索,CFRelease().

分析下面的情況:

在一個(gè)方法里定義了一個(gè)CGColorRef對象:CGColorRef cf

分別通過以下三種方式給cf賦值后,再使用cf時(shí)會(huì)有什么不同呢躏碳?

方式一:

[objc]view plaincopy

UIColor*?color?=?[[UIColoralloc]initWithRed:0.0fgreen:0.0fblue:0.0falpha:1.0f];

cf?=?color.CGColor;

方式二:

[objc]view plaincopy

cf?=?[[UIColoralloc]initWithRed:0.0fgreen:0.0fblue:0.0falpha:1.0f].CGColor;

方式三:

[objc]view plaincopy

cf?=?[UIColorcolorWithRed:0.0fgreen:0.0fblue:0.0falpha:1.0f].CGColor;

方式一和方式三運(yùn)行沒問題搞旭。方式二后再使用cf會(huì)crash,因?yàn)檫@時(shí)cf已經(jīng)是野指針了。

分析如下:

方式一中肄渗,color對象默認(rèn)是strong強(qiáng)引用镇眷,在這個(gè)方法的生命周期內(nèi)都有效,在退出這個(gè)方法時(shí)才會(huì)被自動(dòng)釋放池釋放翎嫡。所以用它的CGColor是沒有問題的欠动。

方式三中類似,colorWithRed:…這是個(gè)類方法惑申,會(huì)返回一個(gè)autorelease對象具伍,對象在自動(dòng)釋放池釋放之前都有效,所以也不會(huì)出問題圈驼。

方式二中人芽,生成的UIColor對象沒有給任何owner,相當(dāng)于一個(gè)weak弱引用绩脆,alloc之后被馬上釋放了萤厅,所以他的CGColor變量也隨之成了野指針。

ARC下OC對象與CF對象橋接:

下面一行代碼:

[objc]view plaincopy

CFStringRef?s1=?(CFStringRef)[[NSStringalloc]initWithFormat:@”Hello,?%d!”,1];

在ARC下面會(huì)報(bào)編譯問題靴迫,并會(huì)給出推薦的解決方案:

[objc]view plaincopy

CFStringRef?s1=?(__bridge?CFStringRef)[[NSStringalloc]initWithFormat:@”Hello,?%d!”,1];

這里NSString生成的是OC的對象惕味,內(nèi)存由ARC負(fù)責(zé)。s1是CF的對象矢劲,內(nèi)存還是需要自己手動(dòng)管理赦拘。兩個(gè)變量轉(zhuǎn)換時(shí)需要添加橋接標(biāo)識慌随。

上面這種情況下不會(huì)crash芬沉,也不會(huì)有內(nèi)存泄露。因?yàn)閍lloc出來的內(nèi)存會(huì)被ARC回收阁猜,這塊內(nèi)存的所有關(guān)系沒變丸逸。

如果后面加上CFRelease(s1);就會(huì)crash,因?yàn)檫@塊內(nèi)存還是歸ARC管的剃袍,這樣會(huì)過度釋放黄刚。

修改一下:

CFStringRef s1 = (__bridge_retained CFStringRef)[[NSString alloc] initWithFormat:@”Hello, %d!”, 1];

這種情況下,對象的所有權(quán)交給CF對象了民效。就需要加上CFRelease(s1);進(jìn)行釋放憔维,否則會(huì)產(chǎn)生泄露。

再看下面代碼:

[objc]view plaincopy

CFUUIDRef?uu?=?CFUUIDCreate(NULL);

CFStringRef?s2=?CFUUIDCreateString(NULL,?uu);

CFRelease(uu);

NSString*?str?=?(__bridge?NSString*)s2;

NSLog(@”STR:%@”,str);

CFRelease(s2);

這里的uu和s2都需要使用CFRelease釋放畏邢,因?yàn)樗麄儾皇荗C對象业扒,并且是create出來的內(nèi)存,并且所有權(quán)沒有被釋放舒萎。

如果改動(dòng)下面一行代碼:

NSString* str = (__bridge_transfer NSString*)s2;

這時(shí)候運(yùn)行程序會(huì)引起crash程储,因?yàn)閟2的所有權(quán)已經(jīng)交給ARC中的str了,ARC會(huì)負(fù)責(zé)釋放這塊內(nèi)存。

這時(shí)候調(diào)用CFRelease(s2);會(huì)造成過度釋放章鲤。所以應(yīng)該把這么行代給去了摊灭。

注:

ARC模式下,自動(dòng)回收只針對Objective-C對象有效败徊,對于使用create,copy,retain等生成的Core Foundation對象還是需要我們手動(dòng)進(jìn)行釋放的帚呼,CFRelease().


由于iOS中CF框架需要自己釋放內(nèi)存,所以ARC的自動(dòng)釋放內(nèi)存就不管用了,需要我們自己釋放,需要使用CFRelease(<#CFTypeRef cf#>)這個(gè)方法來手動(dòng)釋放內(nèi)存.

一:? ARC模式:NSLog(@”Retain count is %ld”, CFGetRetainCount((__bridge CFTypeRef)myObject));

二 : CF框架:NSLog(@”Retain count is %ld”, CFGetRetainCount(myObject));

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市皱蹦,隨后出現(xiàn)的幾起案子萝挤,更是在濱河造成了極大的恐慌,老刑警劉巖根欧,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怜珍,死亡現(xiàn)場離奇詭異,居然都是意外死亡凤粗,警方通過查閱死者的電腦和手機(jī)酥泛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫌拣,“玉大人柔袁,你說我怎么就攤上這事∫熘穑” “怎么了捶索?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長灰瞻。 經(jīng)常有香客問我腥例,道長,這世上最難降的妖魔是什么酝润? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任燎竖,我火速辦了婚禮,結(jié)果婚禮上要销,老公的妹妹穿的比我還像新娘构回。我一直安慰自己,他們只是感情好疏咐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布纤掸。 她就那樣靜靜地躺著,像睡著了一般浑塞。 火紅的嫁衣襯著肌膚如雪借跪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天缩举,我揣著相機(jī)與錄音垦梆,去河邊找鬼匹颤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛托猩,可吹牛的內(nèi)容都是我干的印蓖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼京腥,長吁一口氣:“原來是場噩夢啊……” “哼赦肃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起公浪,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤他宛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后欠气,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厅各,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年预柒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了队塘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宜鸯,死狀恐怖憔古,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淋袖,我是刑警寧澤鸿市,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站即碗,受9級特大地震影響焰情,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拜姿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一烙样、第九天 我趴在偏房一處隱蔽的房頂上張望冯遂。 院中可真熱鬧蕊肥,春花似錦、人聲如沸蛤肌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坎背。三九已至柜思,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炒俱,已是汗流浹背盐肃。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工爪膊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砸王。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓推盛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谦铃。 傳聞我的和親對象是個(gè)殘疾皇子耘成,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

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