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

首頁 > 系統 > iOS > 正文

iOS中多線程的經典崩潰總結大全

2019-10-21 18:42:58
字體:
來源:轉載
供稿:網友

前言

iOS崩潰是讓iOS開發人員比較頭痛的事情,app崩潰了,說明代碼寫的有問題,這時如何快速定位到崩潰的地方很重要。調試階段是比較容易找到出問題的地方的,但是已經上線的app并分析崩潰報告就比較麻煩了。

本文將給大家總結介紹關于iOS中多線程的一些經典崩潰,下面話不多說了,來一起看看詳細的介紹吧。

0x0 Block 回調的崩潰

在MRC環境下,使用Block 來設置下載成功的圖片。當self釋放后,weakSelf變成野指針,接著就悲劇了

 __block ViewController *weakSelf = self; [self.imageView imageWithUrl:@"" completedBlock:^(UIImage *image, NSError *error) {  NSLog(@"%@",weakSelf.imageView.description); }];

0x1 多線程下Setter 的崩潰

Getter & Setter 寫多了,在單線程的情況下,是沒有問題的。但是在多線程的情況下,可能會崩潰。因為[_imageView release]; 這段代碼可能會被執行兩次,oops!

UIKit 不是線程,所以在不是主線程的地方調用UIKit 的東西,有可能在開發階段完全沒問題,直接免測。但是一到線上,崩潰系統可能都是你的崩潰日志。Holy shit!

解決辦法:通過hook 住setNeedsLayout,setNeedsDisplay,setNeedsDisplayInRect來檢查當前調用的線程是否是主線程。

- (void)setImageView:(UIImageView *)imageView{ if (![_imageView isEqual:imageView]) { [_imageView release]; _imageView = [imageView retain]; }}

0x2 更多Setter 類型的崩潰

property 的屬性,寫的最多的就是nonatomic,一般情況下也是沒有問題的!

@interface ViewController ()@property (strong,nonatomic) NSMutableArray *array;@end

跑一下下面這段代碼,你會看到:
malloc: error for object 0x7913d6d0: pointer being freed was not allocated

for (int i = 0; i < 100; i++) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  self.array = [[NSMutableArray alloc] init]; }); } 

原因就是:對象被重復relaese 了。查看一下runtime 源碼

ios,多線程崩潰,ios多線程,ios多線程編程

解決辦法:屬性聲明為atomic.

一個更為常見的例子:

if(handler == nil){ hander = [[Handler alloc] init];}return handler;

如果A,B兩個線程同時訪問到if語句, 此時handler == nil條件滿足, 兩個線程都走到下一句初始化實例.

此時A線程先完成初始化并賦值(這個實例我們叫它a), 然后繼續往后走到其他邏輯.而這時候, B線程開始做初始化并賦值(這個實例我們叫它b), handler將指向B線程初始化出來的對象. 而A初始化出來的實例a因為引用計數減少1(減少到0)而被釋放. 但在A線程中, 代碼還會嘗試訪問a所在的地址, 這個地址里的內容因為被釋放而變得無法預測, 從而導致野指針.

問題還有一個很關鍵的點, 在一個對象的某個方法的調用過程中, 這個對象的引用計數并不會增加, 到導致它如果被釋放, 后續的執行過程中對這個對象的訪問就可能會導致野指針[1].

Exception Type: SIGSEGVException Codes: SEGV_ACCERR at 0x12345678Triggered by Thread: 1

簡單加個鎖就可以解決問題了:

 @synchronized(self){ if(handler == nil) {  hander = [[Handler alloc] init]; } }return handler;

0x3 多線程下對變量的存取

if (self.xxx) { [self.dict setObject:@"ah" forKey:self.xxx];}

大家第一眼看到這樣的代碼,是不是會認為是正確的?因為在設置key的時候已經提前進行了self.xxx為非nil的判斷,只有非nil得情況下才會執行后續的指令。但是,如上代碼只有在單線程的前提下才是正確的。

假設我們將上述代碼目前執行的線程為Thread A,當我們執行完if (self.xxx)的語句之后,此時CPU將執行權切換給了Thread B,而這個時候Thread B中調用了一句self.xxx = nil。 使用局部變量可以解決這個問題

__strong id val = self.xxx;if (val) { [self.dict setObject:@"ah" forKey:val];}

這樣,無論多少線程嘗試對self.xxx進行修改,本質上的val都會保持現有的狀態,符合非nil的判斷。

0x4 dispatch_group 的崩潰

dispatch_group_enter 和 leave 必須是匹配的,不然就會crash . 在多資源下載的時候,往往需要使用多線程并發下載,全部下載完之后通知用戶。開始下載,dispatch_group_enter ,下載完成dispatch_group_leave 。 非常簡單的流程,但是當代碼復雜到一定程度或者是使用了一些第三方庫的時候,就很大可能出問題。

dispatch_group_t serviceGroup = dispatch_group_create();dispatch_group_notify(serviceGroup, dispatch_get_main_queue(), ^{ NSLog(@"Finish downloading :%@", downloadUrls);});// t 是一個包含一堆字符串的數組 [downloadUrls enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { dispatch_group_enter(serviceGroup); SDWebImageCompletionWithFinishedBlock completion = ^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {  dispatch_group_leave(serviceGroup);  NSLog(@"idx:%zd",idx); }; [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString: downloadUrls[idx]]      options:SDWebImageLowPriority      progress:nil             completed:completion];}];

使用多線程進行并發下載,直到所有圖片都下載完成(可以失?。┻M行回調,其中圖片下載使用的是SDWebImage.發生崩潰的場景是:有10 張圖片,分開兩次下載(A & B)。其中在B組里面有一張圖片和A組下載的圖片重復了。假設A組下載對應GroupA ,B組GroupB

下面截取SDWebImage源碼:

dispatch_barrier_sync(self.barrierQueue, ^{ SDWebImageDownloaderOperation *operation = self.URLOperations[url]; if (!operation) {  operation = createCallback();  // ****注意這行****  self.URLOperations[url] = operation;  __weak SDWebImageDownloaderOperation *woperation = operation;  operation.completionBlock = ^{   SDWebImageDownloaderOperation *soperation = woperation;   if (!soperation) return;   if (self.URLOperations[url] == soperation) {    [self.URLOperations removeObjectForKey:url];   };  }; }// ****注意這行****id downloadOperationCancelToken = [operation addHandlersForProgress:progressBlock completed:completedBlock];}

SDWebImage的下載器會根據URL做下載任務對應NSOperation映射,相同的URL會映射到同一個未執行的NSOperation。當A組圖片下載完成后,相同的url 回調是 GroupB 而不是Group A。此時Group B的計數為1 。當B 組圖片全部下載完后,結束計數為 5+1 。因為enter 的次數為5 ,leave 的次數為6 ,因此會崩潰!

0x5 最后一個持有者釋放后的崩潰

對象A被 manager 持有,在A中調用[Manager removeObjectA] 。A對象的retainCount -1, 當retainCount 等于零時,對象A已經開始釋放了。在調用removeObjectA 后,緊接著調用[self doSomething] ,就會崩潰。

- (void)finishEditing{ [Manager removeObject:self]; [self doSomething];}

這種情況一般會發生在數組或者字典包含對象,而且是對象的最后持有者。當在對象處理不好,就會有上面的崩潰。還有一種情況就是,當數組或者字典里面的對象已經被釋放了,當遍歷數組或者取字典里面的值發生崩潰。這種情況,會讓人很崩潰,因為有時候堆棧是這樣的:

Thread 0 Crashed:0 libobjc.A.dylib     0x00000001816ec160 _objc_release :16 (in libobjc.A.dylib)1 libobjc.A.dylib     0x00000001816edae8 __ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv :508 (in libobjc.A.dylib)2 CoreFoundation     0x0000000181f4c9fc __CFAutoreleasePoolPop :28 (in CoreFoundation)3 CoreFoundation     0x0000000182022bc0 ___CFRunLoopRun :1636 (in CoreFoundation)4 CoreFoundation     0x0000000181f4cc50 _CFRunLoopRunSpecific :384 (in CoreFoundation)5 GraphicsServices    0x0000000183834088 _GSEventRunModal :180 (in GraphicsServices)6 UIKit       0x0000000187236088 _UIApplicationMain :204 (in UIKit)7 Tmall4iPhone     0x00000001000b7ae4 main main.m:50 (in Tmall4iPhone)8 libdyld.dylib     0x0000000181aea8b8 _start :4 (in libdyld.dylib)

產生這種堆??赡艿膱鼍笆牵?/p>

釋放Dictionary的時候,某個值(value)因為被其他代碼提前釋放變成野指針, 此時再次被釋放觸發Crash. 如果可以在每個Dictionary釋放的時候, 把所有的key/value打出來, 如果某個key/value剛好被打出來之后, crash就發生了, 那么掛就掛在剛被打出來的key/value上.

0x6 對象的釋放線程要和它處理事情的線程一致

對象A在主線程監聽Notification事件,如果這個對象被其它線程釋放了。此刻,如果對象A 正在執行notification 相關的操作,再訪問對象相關資源就野指針了,發生crash.

0x7 performSelector:withObject:afterDelay:

調用此方法,如果不是在主線程,那么必須要確保當前線程的ruuloop是存在的,performSelector_xxx_afterDelay 依賴runlopp才能執行。另外使用 performSelector:withObject:afterDelay:cancelPreviousPerformRequestsWithTarget 組合的時候要小心。

  • afterDelay會增加receiver的引用計數,cancel則會對應減一
  • 如果在receiver的引用計數只剩下1 (僅為delay)時,調用cancel之后會立即銷毀receiver,后續再調用receiver的方法就會crash
__weak typeof(self) weakSelf = self;[NSObject cancelPreviousPerformRequestsWithTarget:self];if (!weakSelf){//NSLog(@"self被銷毀"); return;}[self doOther];

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩免费在线播放| 久久国产精品视频| 色综合天天狠天天透天天伊人| 97超级碰碰碰| 国内揄拍国内精品少妇国语| 精品国内自产拍在线观看| 欧美国产欧美亚洲国产日韩mv天天看完整| 91精品国产综合久久男男| 7777kkkk成人观看| 久久久久这里只有精品| 95av在线视频| 国产日本欧美一区二区三区| 欧美成人剧情片在线观看| 国产香蕉97碰碰久久人人| 亚洲成人a级网| 欧美成人免费视频| 亚洲色图av在线| 九色精品美女在线| 热草久综合在线| 久久久精品中文字幕| 最近中文字幕2019免费| 久久青草精品视频免费观看| 欧美性视频精品| 精品久久久久久中文字幕一区奶水| 亚洲精品美女久久| 久久亚洲综合国产精品99麻豆精品福利| 亚洲色图偷窥自拍| 97香蕉超级碰碰久久免费软件| 国产成人亚洲综合| 久久久久成人精品| 欧美区在线播放| 国产精品久久久久久久久久新婚| 国产精品国模在线| 欧美性20hd另类| 青青草一区二区| 91福利视频网| 亚洲自拍偷拍一区| 久久91精品国产| 日韩高清有码在线| 国产精品入口免费视| 丝袜美腿精品国产二区| 久久久国产精品视频| 亚洲18私人小影院| 国产午夜精品理论片a级探花| 正在播放欧美一区| 欧美老女人性生活| 欧美极品少妇xxxxⅹ免费视频| 中文字幕国产日韩| 久久久中精品2020中文| 亚洲精品久久久一区二区三区| 欧美成人激情视频| 日韩黄色av网站| 色阁综合伊人av| 久久精品国产成人| 久久久免费电影| 狠狠色狠狠色综合日日小说| 久99久在线视频| 中文欧美日本在线资源| 久久久久五月天| 国产一区二区三区在线播放免费观看| 国产欧美欧洲在线观看| 国产精品午夜视频| 夜夜嗨av色综合久久久综合网| 91免费国产网站| 国产精品久久久久久久电影| 不卡伊人av在线播放| 亚洲在线视频观看| 欧美日韩在线视频一区| 国产综合视频在线观看| www.xxxx精品| 日韩精品999| 韩国v欧美v日本v亚洲| 国产亚洲欧美日韩一区二区| 国产欧美一区二区三区视频| 欧美乱妇40p| 久久久成人精品视频| 欧美体内谢she精2性欧美| 一道本无吗dⅴd在线播放一区| 亚洲人成电影网站色…| 亚洲91精品在线观看| 亚洲欧美制服丝袜| 亚洲人成啪啪网站| 国内揄拍国内精品| 夜夜嗨av色一区二区不卡| 久久综合国产精品台湾中文娱乐网| 日韩精品视频免费专区在线播放| 亚洲视频电影图片偷拍一区| 97久久久久久| 亚洲欧美另类在线观看| 亚洲人成伊人成综合网久久久| 欧美在线视频观看| 北条麻妃在线一区二区| 欧美一级免费看| 福利精品视频在线| 亚洲高清免费观看高清完整版| 热久久视久久精品18亚洲精品| 国产精品美女主播在线观看纯欲| 黑人与娇小精品av专区| 亚洲天堂网站在线观看视频| 色多多国产成人永久免费网站| 黑人精品xxx一区一二区| 国产精品久久久久久久午夜| 精品视频一区在线视频| 日韩欧美成人精品| 不卡中文字幕av| 91精品在线观看视频| 久久婷婷国产麻豆91天堂| 亚洲欧美国内爽妇网| 日本欧美在线视频| 国产精品扒开腿做爽爽爽的视频| 九九热精品在线| 欧美日韩国产麻豆| 日韩精品中文字幕视频在线| 亚洲欧美一区二区激情| 国内精品久久久久久影视8| 一个人看的www久久| 国产精自产拍久久久久久| 日本一本a高清免费不卡| 91高潮在线观看| 日韩在线观看免费高清完整版| 韩国精品久久久999| 欧美黑人极品猛少妇色xxxxx| 日本精品免费一区二区三区| 亚洲国产精品久久久| 欧美成人精品在线| 久久久精品免费视频| 久久久久亚洲精品成人网小说| 日韩在线视频播放| 国产精品视频专区| 亚洲品质视频自拍网| 成人福利在线观看| 精品久久久久久久久国产字幕| 日韩精品免费综合视频在线播放| 亚洲午夜精品久久久久久久久久久久| 中文字幕欧美日韩va免费视频| 国产精品看片资源| 国产午夜精品视频免费不卡69堂| 国产精品视频xxxx| 欧美电影在线观看完整版| 91经典在线视频| 在线精品高清中文字幕| 欧美日韩亚洲一区二区三区| 国产精品国模在线| 中文字幕日韩欧美在线| 亚洲精品国产精品国自产观看浪潮| 庆余年2免费日韩剧观看大牛| 亚洲国产中文字幕在线观看| 26uuu另类亚洲欧美日本老年| 欧美日韩国产在线| 国产精品爱啪在线线免费观看| 日韩免费av在线| 成人精品网站在线观看| 久久久久久久影院| 狠狠操狠狠色综合网| 九色精品免费永久在线| 中文字幕在线看视频国产欧美在线看完整| 日韩精品在线播放| 91精品视频免费| 久久成人精品一区二区三区| 亚洲男人7777| 欧美日韩在线免费观看| 欧美一区二区三区艳史| 国产精品美女久久久免费| 久久影视电视剧凤归四时歌|