24

据我了解,当您尝试访问坏内存时会发生 EXC_BAD_ACCESS (如果我错了,请随时纠正我)?

有没有办法像在try-catchin 中那样捕捉它Java以防止应用程序完全失败?

4

5 回答 5

28

没有; EXC_BAD_ACCESS意味着事情已经严重脱轨。您的程序正在尝试访问无效的内存地址。即内存已损坏,并且没有可预测的恢复。

这可能是内存管理问题。如果您可以重现该问题,请打开 NSZombies 并查看会发生什么。或在此处发布回溯。

请注意,在 iOS/Cocoa 中,try-catch 样式的异常也是不可恢复的。异常不能用于可恢复的错误处理。这就是 NSError 的用途。

于 2013-04-24T20:59:32.737 回答
5

新的 C 库SignalRecovery可以使程序能够从操作系统异常中恢复,例如EXC_BAD_ACCESS. 它可以用于IOS/MacOS/Linux.

示例代码:

signal_try(label) {
    // Add your code need try.
    int* ptr = NULL;
    *ptr = 0;
}
signal_catch(label) {
    // Add your code to process exceptions, or do nothing.
    siginfo_t* info = signal_info();
}
signal_end(label)
// Continue run
于 2019-03-15T09:32:19.470 回答
3

可以使用 try catch,但您首先需要知道导致问题的原因。您可以为当前构建启用 NSZombie 以捕获错误并消除需要。编辑当前方案,启用 NSZombie。

  • 更新 * Swift2+ 现在具有出色的错误处理能力,绝对值得一试。 快速错误处理
于 2013-04-24T20:59:30.127 回答
3

有时您可以main使用信号处理程序将其捕获。但是,除了记录一些东西之外,它不允许您做太多事情。

于 2013-04-24T22:04:34.573 回答
3

如果您想通过关闭捕获或处理崩溃,您可以使用https://github.com/dhatbj/SignalRecovery

C 代码 func 宏在 swift 中不可用,您不能直接调用函数(signal_try、signal_catch、signal_end) 下面是一个如何将闭包作为函数参数传递的示例。

首先,我们需要将完成块传递给 C 代码并返回信号错误。

将此代码添加到 signal_recovery.h:

const char* signalTry(void (*block)(void));

将此代码添加到 signal_recovery.c:

const char* signalTry(void (*block)(void)) {
    
    const char* signalName = "";
    
    signal_try(label0) {
        block();
    }
    signal_catch(label0) {
        signalName = signal_name(signal_info()->si_signo);
    }
    signal_end(label0)
    
    return signalName;
}

在 swift 代码中,您需要调用 C 函数 signalTry 并将闭包作为参数传递给它:

import // C files   

class ExceptionsHandler {    
    
        private static var isReady = false
        
        init() {
            if !Self.isReady {
                Self.isReady = true
                signal_catch_init()
            }
        }
        
        private func cFunction(_ block: @escaping @convention(block) () -> Void) -> (@convention(c) () -> Void) {
            return unsafeBitCast(imp_implementationWithBlock(block), to: (@convention(c) () -> Void).self)
        }
        
        func execute(_ block: @escaping () -> Void) throws {
           
            let cBlock: @convention(c) () -> Void = cFunction {
                block()
            }
    
            let error = signalTry(cBlock)
    
            if let error = error, !String(cString: UnsafePointer<CChar>(error)).isEmpty {
                print("Catched signal \(String(cString: UnsafePointer<CChar>(error)))")
                throw \\ error or exception
            }
        }
    }

当闭包块()内发生错误 EXC_BAD_ACCESS 时,此 C 函数将跳过它,您将捕获它而不会崩溃。

像这样:

try self.exceptionsHandler.execute {
            let a = 3
            let b = 0
            let c = a / b

            // or
            let testArray: [Int] = []
            let number = testArray[100]
        }
于 2021-10-27T08:31:10.150 回答