最近進行iOS 安全黑匣子的測試,在Demo中通過不斷的點擊調加密接口,同時通過蘋果自帶instrument的leak工具監控,發現典型的內存泄漏,監控圖如下:
上圖中紅色的部分表示該操作觸發的代碼有內存泄漏的可能,于是拿出源代碼來研究一番,源代碼如下:
//加密接口
-(IBAction)encrypt:(id)sender {
out?=nil;
NSString?*text =?@"1374112539taobao://?ssoType=AuthorizeApplicationPrefix&appkey=1234&appName=SSO Demo&urlSchemes=ssodemo://&t=13741125391374112539";
NSData?*inputData = [text?dataUsingEncoding:NSUTF8StringEncoding];
out?= [[[TBSecretMgr sharedInstance] encrypt:inputData]retain];
NSString?*test =[[NSString?alloc]?initWithData:out?encoding:NSUTF8StringEncoding];
NSLog(@"encrypt:%@",test);
[test?release];}
//解密接口
- (IBAction)deEncrypt:(id)sender {
NSData?*deEncryptOut = [[TBSecretMgr?sharedInstance]?decrypt:out];
NSString?*outStr = [[NSString?alloc]?initWithData:deEncryptOut?encoding:NSUTF8StringEncoding];
NSLog(@"deencry%@",outStr);
[outStr?release];
}
在分析這2個接口之前,我們需要了解iOS的內存機制,尤其對基本的alloc,retain,release,dealloc需要理解.
alloc ?對象分配后引用計數為1
retain 對象的引用計數+1
copy ? copy一個對象變成新的對象(新內存地址)引用計數為1,原來對象計數不變.
relase 對象引用計數-1,如果為0釋放內存
autorelase 對象引用計數-1,如果為0不馬上釋放.
內存管理的原則就是最終的引用計數要平衡.
如果最后引用計數大于0,則會內存泄漏
如果引用計數等于0還對該對象進行操作,則會出現內存訪問失敗,crash.
此段代碼out返回類型是Nsstring,后加一個retain,在不斷的點擊下,每次引用,都會retain+1,而沒有release操作,導致內存一直被占用,沒有釋放. 解決方案就是把加解密放在一個操作中,不加retain計數.
代碼修改如下,內存泄漏問題解決:
- (IBAction)encrypt:(id)sender {out =nil;NSString *text =nil;NSData *inputData = [text dataUsingEncoding:NSUTF8StringEncoding];out = [[TBSecretMgr sharedInstance] encrypt:inputData];NSString *test =[[NSString alloc] initWithData:out encoding:NSUTF8StringEncoding];NSLog(@"encrypt:%@",test);[test release];NSData *deEncryptOut = [[TBSecretMgr sharedInstance] decrypt:out];NSString *outStr = [[NSString alloc] initWithData:deEncryptOut encoding:NSUTF8StringEncoding];NSLog(@"Dencry%@",outStr);[outStr release];}