objective-c – 使用EXC_BAD_ACCESS阻止回调崩溃

objective-c – 使用EXC_BAD_ACCESS阻止回调崩溃,第1张

概述我有一个自定义的NSOperation子类,用于发出HTTP请求.它接受在NSOperation完成时执行的基于块的回调.一切都有效,但是在尝试执行完成回调时,我遇到了一个奇怪的,间歇性的崩溃.我读过很多基于块的EXEC_BAD_ACCESS问题是由于在将块传递给其他方法时没有正确复制块引起的. 我相信我的问题与我如何利用积木有关.我将在下面为我的应用程序提供一个标准用例.我的问题的根源可能归结为 我有一个自定义的NSOperation子类,用于发出http请求.它接受在NSOperation完成时执行的基于块的回调.一切都有效,但是在尝试执行完成回调时,我遇到了一个奇怪的,间歇性的崩溃.我读过很多基于块的EXEC_BAD_ACCESS问题是由于在将块传递给其他方法时没有正确复制块引起的.

我相信我的问题与我如何利用积木有关.我将在下面为我的应用程序提供一个标准用例.我的问题的根源可能归结为所有权误解了涉及块的地方.

// Perform a http request to a specifIEd endpoint and declare a callback block[self performRequestToEndpoint:@"endpoint" completion:^(httpResponse *response) {    NSLog(@"Completed with response: %@",response);}];// A helper function to avoID having to pass around too many parameters- (voID)performRequestWithEndpoint:(Nsstring *)endpoint completion:(voID (^)(httpResponse *response))completionBlock{    // Make our http request and callback our original completion block when done    [self requestWithMethod:@"GET" path:endpoint completion:^(httpResponse *response) {        if(![response error])        {            // Call our original completion block            completionBlock(response);        }    ];}

当通过requestWithMethod:path:completion:方法分配回调块时,它被复制如下:

@property (nonatomic,copy) voID (^operationCompletionBlock)(httpResponse *response);

这是崩溃的重点:

- (voID)callCompletionBlockWithResponse:(ID)response{    if(self.operationCompletionBlock && !self.isCancelled)    {        self.operationCompletionBlock(response); // crashes here (intermittently)    }    [self finish];}

下面是堆栈跟踪:

* thread #1: tID = 0x2403,0x0000000000000000,stop reason = EXC_BAD_ACCESS (code=1,address=0x0)    frame #0: 0x0000000000000000    frame #1: 0x00007f946b53ed01    frame #2: 0x0000000102da7cf7 Project`-[httpRequest callCompletionBlockWithResponse:] + 215 at httpRequest.m:402    frame #3: 0x0000000102da79e7 Project`__44-[httpRequest connectionDIDFinishLoading:]_block_invoke_0 + 423 at httpRequest.m:381    frame #4: 0x00007fff956fea86 libdispatch.dylib`_dispatch_call_block_and_release + 18    frame #5: 0x00007fff957008f6 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 308    frame #6: 0x00007fff8f07ce7c CoreFoundation`__CFRunLoopRun + 1724    frame #7: 0x00007fff8f07c486 CoreFoundation`CFRunLoopRunspecific + 230    frame #8: 0x00007fff94f1a4d3 HIToolBox`runcurrentEventLoopInMode + 277    frame #9: 0x00007fff94f21781 HIToolBox`ReceiveNextEventCommon + 355    frame #10: 0x00007fff94f2160e HIToolBox`BlockUntilNextEventMatchingListInMode + 62    frame #11: 0x00000001032a6e31 AppKit`_DPSNextEvent + 659    frame #12: 0x00000001032a6735 AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135    frame #13: 0x00000001032a3071 AppKit`-[NSApplication run] + 470    frame #14: 0x000000010351f244 AppKit`NSApplicationMain + 867    frame #15: 0x0000000102d69512 Project`main + 34 at main.m:13    frame #16: 0x0000000102d694e4 Project`start + 52
解决方法 这是在黑暗中拍摄的.您有两个完成块,其中只有一个是您明确复制的(使用该属性).我的心智模型说,completionBlock传递给performRequestWithEndpoint:completion:应该在你传递的块的范围内捕获.但我知道一些偏执的人可能会尝试这样做:

- (voID)performRequestWithEndpoint:(Nsstring *)endpoint                         completion:(voID (^)(httpResponse *response))completionBlock{    voID (^copIEdBlock)(httpResponse *response) = [completionBlock copy];    [self requestWithMethod:@"GET" path:endpoint completion:^(httpResponse *response) {        if(![response error] && copIEdBlock) {            copIEdBlock(response);        }    ];}
总结

以上是内存溢出为你收集整理的objective-c – 使用EXC_BAD_ACCESS阻止回调崩溃全部内容,希望文章能够帮你解决objective-c – 使用EXC_BAD_ACCESS阻止回调崩溃所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1015203.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存