如何为 EXC_BAD_ACCESS 崩溃设置新的 handler/responder
How to set a new handler/responder for EXC_BAD_ACCESS crashes
我正在寻找为 EXC_BAD_ACCESS
覆盖 responder/handler 的方法。这就是我为 signal
崩溃或 NSException
设置处理程序的方式,它工作正常:
NSSetUncaughtExceptionHandler(newExceptionHandler)
signal(SIGABRT, newSignalHandler)
signal(SIGILL, newSignalHandler)
我试过了,但没有被调用:
signal(EXC_BAD_ACCESS, newSignalHandler)
有什么想法吗?
如果您没有使用现有的崩溃报告器(它们很难自己编写,在处理损坏的内存等时),您可能会查看它们的来源以了解它们正在处理哪些信号。例如,PLCrashReporter's PLCrashReporter.m hooks onto SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, and SIGTRAP, which seems to be the usual list for crash handlers. EXC_BAD_ACCESS should turn into either SIGBUS or SIGSEGV. Writing re-entrant code correctly in signal handlers is extremely difficult(不能使用任何 ObjC 或其中的大多数 C API),所以要小心——尽管我猜如果你已经崩溃了,也不会造成更多伤害。但是你越小心,你处理的异常就越多而不会进一步崩溃。
正如 Carl 提到的那样,由于各种原因,拦截 iOS(和 macOS)上的崩溃事件充满了危险。我有一段时间是 Crashlytics SDK 的维护者,我强烈建议不要这样做。
但是,这绝对是可能的。
信号、异常(ObjC 或 C++)和 mach 异常之间的关系似乎让人们很困惑。这些都是非常不同的东西。
在 iOS(和 tvOS、macOS)上,终止进程的事件是 mach 异常。实际上,这些是您可以拦截的低级事件。当您看到 EXC_
前缀时,您知道您正在查看 mach 异常。我相信这些都在 mach/exception.h
.
中定义
现在,iOS 有一个有趣的实现,如果没有 mach 异常处理程序,OS 会将事件转换为 unix 信号。 signal
函数可用于拦截这些。由于 EXC_BAD_ACCESS
不是 unix 信号,因此它不是 signal
函数的有效参数。但是,您可以向列出的那些信号添加处理程序,它们会为您提供大致相同的信息。
Mach 异常是一种更强大、更安全的拦截此类事件的机制。不幸的是,它们还需要复杂得多的处理系统。信号有各种各样的问题,但是用起来简单多了。
我很想知道你想做什么,以防万一有更好的方法来实现你所追求的目标。
同样,我会避免走这条路。这不值得你花时间。让事情正常运转是很有挑战性的,当你这样做的时候,你会陷入一种虚假的安全感。您甚至可能认为一切正常,因为您的代码有时会完全出错,您永远不会知道,您只会时不时地从随机挂起的用户那里收到奇怪的报告。
我正在寻找为 EXC_BAD_ACCESS
覆盖 responder/handler 的方法。这就是我为 signal
崩溃或 NSException
设置处理程序的方式,它工作正常:
NSSetUncaughtExceptionHandler(newExceptionHandler)
signal(SIGABRT, newSignalHandler)
signal(SIGILL, newSignalHandler)
我试过了,但没有被调用:
signal(EXC_BAD_ACCESS, newSignalHandler)
有什么想法吗?
如果您没有使用现有的崩溃报告器(它们很难自己编写,在处理损坏的内存等时),您可能会查看它们的来源以了解它们正在处理哪些信号。例如,PLCrashReporter's PLCrashReporter.m hooks onto SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, and SIGTRAP, which seems to be the usual list for crash handlers. EXC_BAD_ACCESS should turn into either SIGBUS or SIGSEGV. Writing re-entrant code correctly in signal handlers is extremely difficult(不能使用任何 ObjC 或其中的大多数 C API),所以要小心——尽管我猜如果你已经崩溃了,也不会造成更多伤害。但是你越小心,你处理的异常就越多而不会进一步崩溃。
正如 Carl 提到的那样,由于各种原因,拦截 iOS(和 macOS)上的崩溃事件充满了危险。我有一段时间是 Crashlytics SDK 的维护者,我强烈建议不要这样做。
但是,这绝对是可能的。
信号、异常(ObjC 或 C++)和 mach 异常之间的关系似乎让人们很困惑。这些都是非常不同的东西。
在 iOS(和 tvOS、macOS)上,终止进程的事件是 mach 异常。实际上,这些是您可以拦截的低级事件。当您看到 EXC_
前缀时,您知道您正在查看 mach 异常。我相信这些都在 mach/exception.h
.
现在,iOS 有一个有趣的实现,如果没有 mach 异常处理程序,OS 会将事件转换为 unix 信号。 signal
函数可用于拦截这些。由于 EXC_BAD_ACCESS
不是 unix 信号,因此它不是 signal
函数的有效参数。但是,您可以向列出的那些信号添加处理程序,它们会为您提供大致相同的信息。
Mach 异常是一种更强大、更安全的拦截此类事件的机制。不幸的是,它们还需要复杂得多的处理系统。信号有各种各样的问题,但是用起来简单多了。
我很想知道你想做什么,以防万一有更好的方法来实现你所追求的目标。
同样,我会避免走这条路。这不值得你花时间。让事情正常运转是很有挑战性的,当你这样做的时候,你会陷入一种虚假的安全感。您甚至可能认为一切正常,因为您的代码有时会完全出错,您永远不会知道,您只会时不时地从随机挂起的用户那里收到奇怪的报告。