3

正如我所提到的,我正在尝试恢复崩溃的线路以及它发生的功能。

我需要提到我已经尝试了 AppDelegate 中的下一个代码,并且我得到了没有符号化的堆栈和类以及抛出的错误:

NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);

void uncaughtExceptionHandler(NSException *exception) {

    NSLog(@"Exception description - %@",[exception description]);
    NSLog(@"Exception name - %@", [exception name]);
    NSLog(@"Reason - %@", [exception reason]);
    NSLog(@"\n\n - %@", [exception callStackSymbols]);
    NSLog(@"\n\n - %@", [exception callStackReturnAddresses]);
}

但是通过使用这些我没有得到崩溃的线路,因为我打算将它保存在 CoreData 中。

此外,我对 xcode 方法不感兴趣:“添加异常断点”或其他方法:XCode > Window > Devices > 查看设备上的崩溃日志、测试飞行方法或在应用程序中将其他框架实现为 Crashlytics。

我提到这些是因为我对通过代码完成的方式非常感兴趣。

还可以在制作应用存档时获取应用存档的 dsym,并使用使用 Bash 编写的 RunScript 将其上传到服务器。因此,如果需要达到崩溃线,我可以使用 dsym。

另外我知道可以使用下一个方法来获取当前代码行:LINE和 _FUNCTION__ 来获取函数名称。

此外,如果您可以提供来自开源 PLCrashReporter 的代码示例,说明他们是如何做到的,我会非常感激。

比你们都提前!:)

4

2 回答 2

4

基本上有两种类型的崩溃:

  1. 未捕获的异常,可以使用类似于您的代码捕获
  2. 基于信号的崩溃,可以使用信号处理程序(或 Mach 异常处理程序,但不会捕获所有信号)捕获

然后捕获任何这些崩溃,您需要获取(所有线程的)堆栈跟踪。[NSException callStackSymbols]将为您提供一些符号(仅用于异常崩溃),对于许多操作系统符号,它只会显示redacted,对于您的应用程序,如果您不从二进制文件中删除它们,它将提供一些符号。建议从二进制文件中删除符号以减小文件大小(很多),而且这些符号也永远不会提供文件名和行号。

因此,您需要从堆栈帧中获取以下信息:二进制、二进制 UUID、cpu 架构和内存地址。[NSException callStackReturnAddresses]将为您提供内存地址,但仅针对基于异常的崩溃。此外,它不提供与内存地址对应的二进制图像。

因此,您需要获取具有每个二进制图像覆盖的内存地址范围的二进制图像列表,以及一种获取线程堆栈帧的内存地址的方法,也用于非基于异常的崩溃。如果想了解这是怎么回事,基本上可以看一下所有 PLCrashReporters 代码,因为这是开源项目的目的,解释如此复杂的场景不在 StackOverflow 的范围内。阅读代码、文档并学习 :) 给你一个简短的要点:不要自己做,只需使用 PLCrashReporter。

现在要获取包括文件名和行号在内的符号,您需要使用发生崩溃报告的设备的相应操作系统版本和相应 CPU 架构的操作系统符号来符号化崩溃报告。您还需要从您的应用程序触发崩溃报告的确切二进制文件(和框架)中的符号 (dSYM) 包。每个二进制图像都有一个唯一的 UUID,并且您用来获取符号的符号文件需要对于相同的 CPU 架构具有相同的 UUID。

现在您需要运行该工具atos以从特定符号文件中获取特定内存地址的符号。以下堆栈溢出答案显示了如何做到这一点:https ://stackoverflow.com/a/13576028/474794

作为替代方案,您可以使用symbolicatecrash.plXcode 附带的脚本并获取 Apple 标准格式的崩溃报告(PLCrashReporter 有一个转换工具可以从其更紧凑的报告中创建此类报告)。

于 2016-01-08T09:34:45.203 回答
2

您可以__PRETTY_FUNCTION__在日志中使用,这将为您提供函数的行、类和名称。

NSLog(@"%@", __PRETTY_FUNCTION__);

您可以使用您喜欢的任何其他信息填写日志的其余部分。

于 2016-01-07T21:17:54.900 回答