如何捕捉 Swift 崩溃并进行一些日志记录
Posted
技术标签:
【中文标题】如何捕捉 Swift 崩溃并进行一些日志记录【英文标题】:How to catch a Swift crash and do some logging 【发布时间】:2016-07-19 10:03:42 【问题描述】:在 Objective-C 中,NSSetUncaughtExceptionHandler
可以注册一些功能,以便在最后一刻记录异常。
这并没有捕捉到 Swift 崩溃的东西。
在 Swift 中是否可以在全球范围内做这样的事情?例如。如果在 Swift 代码中发生崩溃,请进行一些日志记录,例如强制解包 nil 可选。
具体来说,我正在做一个实用程序来记录应用程序中的网络流量,如果发生崩溃,我想将内存中的数据刷新到磁盘。
【问题讨论】:
我想也许 Apple 并没有像 Refactor 那样为此工作。 【参考方案1】:NSSetUncaughtExceptionHandler
仅适用于 NSExceptions。请参阅this SO 答案以获得精彩的解释。
要捕获 Swift 运行时错误,请实现 SIGTRAP
的信号处理程序。据我所知,如果 Swift 代码在运行时检测到意外情况,它将以 SIGTRAP
异常类型终止程序,即只有 SIGTRAP
有助于捕获 Swift 错误,其余为 SIGSEGV
、SIGBUS
、@987654331 @ 不工作。
我在this apple 链接中找到了此信息。
如果您的代码是 Objective-C 和 Swift 的混合体,则同时实现 NSSetUncaughtExceptionHandler
和信号处理程序来处理崩溃。
要了解和实现信号处理,请参阅this 链接。
希望这会有所帮助。
【讨论】:
我为大多数信号添加了一个信号处理程序(包括SIGTRAP
),但是它不处理“致命错误:在展开可选值时意外发现 nil”。我还添加了一个带有NSSetUncaughtExceptionHandler()
的异常处理程序...
@NicolasMiari 在问题 SIGILL
的取消引用为零。【参考方案2】:
Swift 5 你可以像这样处理应用崩溃
NSSetUncaughtExceptionHandler (exception) in
let stack = exception.callStackReturnAddresses
print("Stack trace: \(stack)")
【讨论】:
【参考方案3】:NSSetUncaughtExceptionHandler(&HandleException);
signal(SIGABRT, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGFPE, SignalHandler);
signal(SIGBUS, SignalHandler);
signal(SIGPIPE, SignalHandler);
这适用于大多数情况。但我也试图找到一些方法来捕捉所有的崩溃。好吧,如果你 comd+click 到那些信号来查看文档,你会发现有 20 多种信号,我做的是 signal(,) 几乎所有类型的信号。这似乎可行,但可能仍然无法收集一些崩溃。
【讨论】:
【参考方案4】:您的问题涉及多个方面,让我尝试回答:
NSSetUncaughtExceptionHandler
仅捕获未捕获的异常,这只是可能崩溃的一小部分。
Objective-C 中的异常被定义为致命的,不建议捕获它们,更不建议运行任何非异步安全代码,包括任何 Objective-C 和 Swift 代码
要捕获崩溃,您需要设置信号处理程序,然后仅在崩溃时运行异步安全代码,这只是 C 的一小部分。尤其是您可能根本不会在崩溃时分配新内存。
请记住,当您的应用程序崩溃时,它处于高度不稳定的代码中,并且对象或变量引用可能指向完全出乎意料的东西。所以你真的不应该在崩溃时做任何事情。
处理崩溃的最佳开源方法是使用PLCrashReporter,它还提供了在崩溃时调用代码的方法。但同样,这必须是异步安全的。
根据您的具体情况:您不应该这样做,也不要尝试这样做。这可能会导致用户数据损坏或丢失更多数据。该应用程序因严重问题而严重崩溃,而不是解决问题。
【讨论】:
以上是关于如何捕捉 Swift 崩溃并进行一些日志记录的主要内容,如果未能解决你的问题,请参考以下文章