You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Objective-C中dispatch_async触发EXC_BAD_ACCESS崩溃问题求助

问题分析:dispatch_async触发EXC_BAD_ACCESS崩溃的原因与解决办法

相关代码

- (void)stopCurrentSessionFromSuite:(NSNotification*)notification{ 
    isCloseCurrentSession = YES; 
    dispatch_async(self.dataSendingQueue, ^{ 
        CARD8 messageToDisableSession = rpcHostDisableMsg; 
        [readerNwriter writeExact:(char*)&messageToDisableSession ofLenght:sizeof(CARD8) secApplied:NO]; 
    }); 
    [rpcCaptureMgr stopCaptureSession]; 
}

崩溃信息

系统唤醒时长:1400秒
系统完整性保护:已启用
崩溃线程:0 调度队列:com.apple.main-thread
异常类型:EXC_BAD_ACCESS (SIGSEGV) 异常代码:
KERN_INVALID_ADDRESS at 0x0000000000000070 异常说明:
EXC_CORPSE_NOTIFY
终止信号:段错误:11 终止原因:
命名空间 SIGNAL, 代码 0xb 终止进程: 异常处理程序 [0]
0x70附近的VM区域:--> __TEXT 000000010871a000-000000010873a000 [ 128K] r-x/rwx SM=COW /Applications/RemotePCSuite/*/RemotePCDesktop.app/Contents/MacOS/RemotePCDesktop
线程0崩溃:: 调度队列: com.apple.main-thread 0
libdispatch.dylib 0x00007fff72de50db _dispatch_continuation_async + 5
1 com.prosoftnet.remotepcDesktop 0x0000000108727fd5 -[RPCDesktopAppDelegate stopCurrentSessionFromSuite:] + 104
2 com.apple.CoreFoundation 0x00007fff4b7a333c CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER + 12
3 com.apple.CoreFoundation 0x00007fff4b7a32cf _CFXRegistrationPost_block_invoke + 63
4 com.apple.CoreFoundation 0x00007fff4b7ab92c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK + 12
5 com.apple.CoreFoundation 0x00007fff4b78e8a3 __CFRunLoopDoBlocks + 275
6 com.apple.CoreFoundation 0x00007fff4b78e668 __CFRunLoopRun + 3128
7 com.apple.CoreFoundation 0x00007fff4b78d797 CFRunLoopRunSpecific + 487
8 com.apple.HIToolbox 0x00007fff4aaa2866 RunCurrentEventLoopInMode + 286
9 com.apple.HIToolbox 0x00007fff4aaa25d6 ReceiveNextEventCommon + 613
10 com.apple.HIToolbox 0x00007fff4aaa2354 _BlockUntilNextEventMatchingListInModeWithFilter + 64
11 com.apple.AppKit 0x00007fff48d9fa23 _DPSNextEvent + 2085
12 com.apple.AppKit 0x00007fff49534e6c -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
13 com.apple.AppKit 0x00007fff48d94831 -[NSApplication run] + 764
14 com.apple.AppKit 0x00007fff48d639d2 NSApplicationMain + 804
15 libdyld.dylib 0x00007fff72e0c145 start + 1

崩溃原因拆解

从堆栈和错误地址来看,这个崩溃的核心原因是传入dispatch_async的队列对象(self.dataSendingQueue)已经变成了野指针,或者self本身已经被提前释放,导致访问self.dataSendingQueue时踩了无效内存:

  • 错误地址0x0000000000000070是空指针偏移出来的,说明我们尝试访问的对象已经被系统回收了;
  • 崩溃发生在_dispatch_continuation_async这一步,说明GCD在尝试处理我们传入的队列时,发现队列是无效的(已释放),直接触发了段错误。

另外还要注意,block里直接访问readerNwriter也可能有同样的风险——如果这个对象是self的属性,那当self被释放后,它也会变成野指针。

具体解决方案

针对这些问题,我们可以分几步来修复:

1. 确保队列的生命周期正确

首先检查dataSendingQueue的声明,必须用强引用(strong)来持有:

@property (nonatomic, strong) dispatch_queue_t dataSendingQueue;

然后在类的初始化方法(比如init或者awakeFromNib)中创建队列,保证它的生命周期和当前对象一致:

- (instancetype)init {
    self = [super init];
    if (self) {
        _dataSendingQueue = dispatch_queue_create("com.yourcompany.remotepc.dataSending", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

ARC环境下不需要手动释放GCD队列,所以不要调用dispatch_release这类方法。

2. 用弱引用-强引用避免self提前释放

在异步block中,我们需要确保self不会被提前释放,同时避免循环引用,所以用弱引用包裹self,在block内部再转成强引用做检查:

- (void)stopCurrentSessionFromSuite:(NSNotification*)notification{ 
    isCloseCurrentSession = YES; 
    __weak typeof(self) weakSelf = self;
    dispatch_async(weakSelf.dataSendingQueue, ^{ 
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return; // 如果self已经释放,直接终止任务
        
        CARD8 messageToDisableSession = rpcHostDisableMsg; 
        [strongSelf.readerNwriter writeExact:(char*)&messageToDisableSession ofLenght:sizeof(CARD8) secApplied:NO]; 
    }); 
    [rpcCaptureMgr stopCaptureSession]; 
}

这样即使self在异步任务执行前被释放,block里也会直接返回,不会访问无效内存。

3. 增加队列的空值检查

在调用dispatch_async之前,先确认队列是否有效,避免传入nil或者野指针:

- (void)stopCurrentSessionFromSuite:(NSNotification*)notification{ 
    isCloseCurrentSession = YES; 
    
    if (!self.dataSendingQueue) {
        NSLog(@"Warning: dataSendingQueue is invalid, skipping async task");
        [rpcCaptureMgr stopCaptureSession];
        return;
    }
    
    __weak typeof(self) weakSelf = self;
    dispatch_async(self.dataSendingQueue, ^{ 
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return;
        
        CARD8 messageToDisableSession = rpcHostDisableMsg; 
        [strongSelf.readerNwriter writeExact:(char*)&messageToDisableSession ofLenght:sizeof(CARD8) secApplied:NO]; 
    }); 
    [rpcCaptureMgr stopCaptureSession]; 
}

内容的提问来源于stack exchange,提问作者Raghavendra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:52:16