AFNetwork在URLSession:dataTask:didReceiveResponse:completionHandler中崩溃排查
AFURLSessionManager回调崩溃问题
问题描述
应用在AFURLSessionManager.m文件的URLSession:dataTask:didReceiveResponse:completionHandler方法第4行崩溃,疑似关联的业务对象self已被释放。
相关代码
添加回调的Func方法
- (void) Func:(AFHTTPSessionManager *)sessionManager { @weakify(self); [sessionManager setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSURLResponse * _Nonnull response) { @strongify(self); if (!self) { return NSURLSessionResponseCancel; } ...... } ...... }
崩溃所在的AFURLSessionManager方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { 1 NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow; 2 3 if (self.dataTaskDidReceiveResponse) { 4 disposition = self.dataTaskDidReceiveResponse(session, dataTask, response); // 原文件第1115行 5 } 6 7}
崩溃堆栈
Exception Type: SIGSEGV Exception Codes: SEGV_ACCERR at 0x58fe10485d20 Thread 13 Crashed: 0 libobjc.A.dylib 0x000000019d5f9c20 objc_msgSend 1 APPInfo 0x0000000105204e0c -[AFURLSessionManager URLSession:dataTask:didReceiveResponse:completionHandler:] at AFURLSessionManager.m:1115:28 2 CFNetwork 0x00000001a54c9934 CFURLConnectionCreateWithProperties 3 Foundation 0x19e75f2f0 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ 4 Foundation 0x19e7334a0 -[NSBlockOperation main] 5 Foundation 0x19e733430 __NSOPERATION_IS_INVOKING_MAIN__ 6 Foundation 0x19e6f47d8 -[NSOperation start] 7 Foundation 0x19e6f450c __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ 8 Foundation 0x19e6f9c20 __NSOQSchedule_f 9 libdispatch.dylib 0x1ab8c1114 _dispatch_block_async_invoke2 10 libdispatch.dylib 0x1ab8b1fdc _dispatch_client_callout 11 libdispatch.dylib 0x1ab8b546c _dispatch_continuation_pop 12 libdispatch.dylib 0x1ab8b4ad4 _dispatch_async_redirect_invoke 13 libdispatch.dylib 0x1ab8c3a6c _dispatch_root_queue_drain 14 libdispatch.dylib 0x1ab8c4284 _dispatch_worker_thread2 15 libsystem_pthread.dylib 0x1f133bdbc _pthread_wqthread 16 libsystem_pthread.dylib 0x1f133bb98 start_wqthread
原因分析
崩溃触发于objc_msgSend,说明调用消息时目标对象已被释放:
- 尽管在回调block内部做了
@weakify/strongify及self空值检查,但持有该block的AFHTTPSessionManager实例可能已被提前释放,导致调用block时出现野指针; - block执行过程中访问了除
self外的其他已释放对象; - 多线程竞态:
self在主线程被释放的同时,block在后台线程完成空值检查后访问self的属性/方法,引发崩溃。
解决方案
- 管理AFHTTPSessionManager生命周期:建议使用单例模式维护
AFHTTPSessionManager实例,确保其生命周期覆盖所有网络请求周期,避免局部实例被提前释放; - 主动清理回调与任务:在业务对象(即block中的
self)销毁时,主动调用sessionManager的invalidateAndCancel或cancelAllTasks方法,同时清空dataTaskDidReceiveResponseBlock; - 强化空值检查:在block内部,对所有要访问的对象(包括
self的属性、其他关联实例)都做空值判断; - 线程安全保障:若涉及多线程操作
self,可通过加锁或GCD串行队列确保self的访问与释放操作互斥。
内容的提问来源于stack exchange,提问作者Berte Colin
相关产品推荐
相关产品推荐

