据我了解,当您尝试访问坏内存时会发生 EXC_BAD_ACCESS (如果我错了,请随时纠正我)?
有没有办法像在try-catch
in 中那样捕捉它Java
以防止应用程序完全失败?
据我了解,当您尝试访问坏内存时会发生 EXC_BAD_ACCESS (如果我错了,请随时纠正我)?
有没有办法像在try-catch
in 中那样捕捉它Java
以防止应用程序完全失败?
没有; EXC_BAD_ACCESS
意味着事情已经严重脱轨。您的程序正在尝试访问无效的内存地址。即内存已损坏,并且没有可预测的恢复。
这可能是内存管理问题。如果您可以重现该问题,请打开 NSZombies 并查看会发生什么。或在此处发布回溯。
请注意,在 iOS/Cocoa 中,try-catch 样式的异常也是不可恢复的。异常不能用于可恢复的错误处理。这就是 NSError 的用途。
新的 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
可以使用 try catch,但您首先需要知道导致问题的原因。您可以为当前构建启用 NSZombie 以捕获错误并消除需要。编辑当前方案,启用 NSZombie。
有时您可以main
使用信号处理程序将其捕获。但是,除了记录一些东西之外,它不允许您做太多事情。
如果您想通过关闭捕获或处理崩溃,您可以使用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]
}