KSCrash

终极崩溃报告器

又一个崩溃报告器?为什么?

因为现有的崩溃报告器确实会报告崩溃,但它们本可以做得更多。以下是 KSCrash 的一些主要特性

KSCrash 处理以下类型的崩溃

KSCrash 可以向以下服务器报告

以下是它可以生成的一些报告示例。

新特性?

寻求帮助!

在过去的几年里,我的生活发生了很大的变化,我无法继续像以前那样维护 KSCrash 了。

I want you

我正在寻找有人来帮助我维护这个软件包,确保问题得到处理,合并得到正确审查,并且代码质量保持在高水平。请亲自联系我(kstenerud 在我的 gmail 地址)或在 kstenerud#313 中发表评论

非常非常非常初步的 Android 支持。

我指的是 *初步*。大多数东西都无法工作,但它可以编译。如果您想玩玩,请查看 Android 子目录。

C++ 异常处理

没错!通常,如果您的应用程序由于未捕获的 C++ 异常而终止,您只会得到这个

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x9750ea6a 0x974fa000 + 84586 (__pthread_kill + 10)
1   libsystem_sim_c.dylib           0x04d56578 0x4d0f000 + 292216 (abort + 137)
2   libc++abi.dylib                 0x04ed6f78 0x4ed4000 + 12152 (abort_message + 102)
3   libc++abi.dylib                 0x04ed4a20 0x4ed4000 + 2592 (_ZL17default_terminatev + 29)
4   libobjc.A.dylib                 0x013110d0 0x130b000 + 24784 (_ZL15_objc_terminatev + 109)
5   libc++abi.dylib                 0x04ed4a60 0x4ed4000 + 2656 (_ZL19safe_handler_callerPFvvE + 8)
6   libc++abi.dylib                 0x04ed4ac8 0x4ed4000 + 2760 (_ZSt9terminatev + 18)
7   libc++abi.dylib                 0x04ed5c48 0x4ed4000 + 7240 (__cxa_rethrow + 77)
8   libobjc.A.dylib                 0x01310fb8 0x130b000 + 24504 (objc_exception_rethrow + 42)
9   CoreFoundation                  0x01f2af98 0x1ef9000 + 204696 (CFRunLoopRunSpecific + 360)
...

无法追踪异常是什么或从哪里抛出的!

现在有了 KSCrash,您可以获得未捕获的异常类型、描述以及抛出的位置

Application Specific Information:
*** Terminating app due to uncaught exception 'MyException', reason: 'Something bad happened...'

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   Crash-Tester                    0x0000ad80 0x1000 + 40320 (-[Crasher throwUncaughtCPPException] + 0)
1   Crash-Tester                    0x0000842e 0x1000 + 29742 (__32-[AppDelegate(UI) crashCommands]_block_invoke343 + 78)
2   Crash-Tester                    0x00009523 0x1000 + 34083 (-[CommandEntry executeWithViewController:] + 67)
3   Crash-Tester                    0x00009c0a 0x1000 + 35850 (-[CommandTVC tableView:didSelectRowAtIndexPath:] + 154)
4   UIKit                           0x0016f285 0xb4000 + 766597 (-[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1194)
5   UIKit                           0x0016f4ed 0xb4000 + 767213 (-[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 201)
6   Foundation                      0x00b795b3 0xb6e000 + 46515 (__NSFireDelayedPerform + 380)
7   CoreFoundation                  0x01f45376 0x1efa000 + 308086 (__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22)
8   CoreFoundation                  0x01f44e06 0x1efa000 + 306694 (__CFRunLoopDoTimer + 534)
9   CoreFoundation                  0x01f2ca82 0x1efa000 + 207490 (__CFRunLoopRun + 1810)
10  CoreFoundation                  0x01f2bf44 0x1efa000 + 204612 (CFRunLoopRunSpecific + 276)
...

自定义崩溃 & 堆栈跟踪

您现在可以报告您自己的自定义崩溃和堆栈跟踪(想想脚本语言)

- (void) reportUserException:(NSString*) name
                  reason:(NSString*) reason
              lineOfCode:(NSString*) lineOfCode
              stackTrace:(NSArray*) stackTrace
        terminateProgram:(BOOL) terminateProgram;

有关详细信息,请参阅 KSCrash.h。

不稳定特性

以下特性应被视为“不稳定”并且默认情况下处于禁用状态

如何构建 KSCrash

  1. 选择 KSCrash 方案。
  2. 选择 iOS Device
  3. Products 菜单中选择 Archive

构建完成后,它将在 Finder 中显示 framework。您可以像使用任何其他 framework 一样使用它。

如何使用 KSCrash

  1. 将 framework 添加到您的项目(或将 KSCrash 项目添加为依赖项)

  2. 将以下系统 framework 和库添加到您的项目中

    • libc++.dylib (较新版本中为 libc++.tbd)
    • libz.dylib (较新版本中为 libz.tbd)
    • MessageUI.framework (仅限 iOS)
    • SystemConfiguration.framework
  3. 在您的 Build Settings 中,将标志 "-ObjC" 添加到 Other Linker Flags

  4. 将以下内容添加到您的应用程序代理中的 [application: didFinishLaunchingWithOptions:] 方法

#import <KSCrash/KSCrash.h>
// Include to use the standard reporter.
#import <KSCrash/KSCrashInstallationStandard.h>
// Include to use Quincy or Hockey.
#import <KSCrash/KSCrashInstallationQuincyHockey.h>
// Include to use the email reporter.
#import <KSCrash/KSCrashInstallationEmail.h>
// Include to use Victory.
#import <KSCrash/KSCrashInstallationVictory.h>

- (BOOL)application:(UIApplication*) application didFinishLaunchingWithOptions:(NSDictionary*) launchOptions
{
KSCrashInstallationStandard* installation = [KSCrashInstallationStandard sharedInstance];
installation.url = [NSURL URLWithString:@"http://put.your.url.here"];

// OR:

KSCrashInstallationQuincy* installation = [KSCrashInstallationQuincy sharedInstance];
installation.url = [NSURL URLWithString:@"http://put.your.url.here"];

// OR:

KSCrashInstallationHockey* installation = [KSCrashInstallationHockey sharedInstance];
installation.appIdentifier = @"PUT_YOUR_HOCKEY_APP_ID_HERE";

// OR:

KSCrashInstallationEmail* installation = [KSCrashInstallationEmail sharedInstance];
installation.recipients = @[@"some@email.address"];

// Optional (Email): Send Apple-style reports instead of JSON
[installation setReportStyle:KSCrashEmailReportStyleApple useDefaultFilenameFormat:YES];

// Optional: Add an alert confirmation (recommended for email installation)
[installation addConditionalAlertWithTitle:@"Crash Detected"
                                 message:@"The app crashed last time it was launched. Send a crash report?"
                               yesAnswer:@"Sure!"
                                noAnswer:@"No thanks"];

// OR:

KSCrashInstallationVictory* installation = [KSCrashInstallationVictory sharedInstance];
installation.url = [NSURL URLWithString:@"https://put.your.url.here/api/v1/crash/<application key>"];

[installation install];
    …
}

这将安装崩溃监视系统(拦截崩溃并将报告存储到磁盘)。请注意,您可以并且可能需要为各种安装设置其他属性。

准备好发送任何未完成的崩溃报告后,调用以下方法

[installation sendAllReportsWithCompletion:^(NSArray *filteredReports, BOOL completed, NSError *error)
{
 // Stuff to do when report sending is complete
}];

推荐阅读

如果可能,您应该阅读以下头文件,以充分了解 KSCrash 具有哪些功能以及如何使用它们

了解 KSCrash 代码库

我写了一个快速代码之旅 here

高级用法

启用设备端符号化

设备端符号化要求最终版本中存在基本符号。要启用此功能,请转到应用程序的构建设置,并将 Strip Style 设置为 Debugging Symbols。这样做会将最终二进制文件的大小增加约 5%,但您会获得设备端符号化。

启用高级功能

KSCrash 具有高级功能,在检查野外崩溃报告时非常有用。有些涉及小的权衡,因此大多数默认情况下处于禁用状态。

自定义用户数据 (KSCrash.h 中的 userInfo)

您可以通过在 KSCrash.h 中设置 userInfo 属性,将自定义用户数据存储到下一个崩溃报告中。

僵尸追踪 (KSCrashMonitorType.h 中的 KSCrashMonitorTypeZombie)

KSCrash 能够检测僵尸实例(指向已释放对象的悬空指针)。它通过记录任何被释放对象的地址和类来实现这一点。它将这些值存储在缓存中,并以已释放对象的地址作为键。这意味着您设置的缓存大小越小,发生哈希冲突并丢失有关先前已释放对象的信息的可能性就越大。

启用僵尸追踪后,KSCrash 还会检测到丢失的 NSException 并打印其内容。某些类型的内存损坏或堆栈损坏崩溃可能会导致异常提前释放,从而进一步阻碍您调试应用程序,因此此功能有时会非常有用。

权衡:僵尸追踪以增加对象释放的极小开销为代价,并占用一些保留内存。

死锁检测 (KSCrashMonitorType.h 中的 KSCrashMonitorTypeMainThreadDeadlock)

警告警告警告警告警告警告警告

此功能不稳定!它可能会误报并使您的应用程序崩溃!

如果您的主线程死锁,您的用户界面将变得无响应,并且用户将不得不手动关闭应用程序(这将不会生成崩溃报告)。启用死锁检测后,会设置一个看门狗计时器。如果任何东西使主线程保持运行时间长于看门狗计时器持续时间,KSCrash 将关闭应用程序并为您提供一个堆栈跟踪,显示主线程当时正在做什么。

这很棒,但您必须小心:应用程序初始化通常发生在主线程上。如果您的初始化代码花费的时间超过看门狗计时器,您的应用程序将在启动期间被强制关闭!如果您启用此功能,您必须确保您的 *任何* 正常运行的代码都不会使主线程保持运行时间超过看门狗值!同时,您需要将计时器设置为足够低的值,以便用户不会变得不耐烦并在看门狗触发之前手动关闭应用程序!

权衡:死锁检测,但您必须更加小心在主线程上运行的内容!

内存自省 (KSCrash.h 中的 introspectMemory)

当应用程序崩溃时,通常内存中存在堆栈、寄存器甚至异常消息所引用的对象和字符串。启用后,KSCrash 将检查这些内存区域并将其内容存储在崩溃报告中。

您还可以通过在 KSCrash 中设置 doNotIntrospectClasses 属性来指定不应被检查的类列表。

自定义崩溃处理代码 (KSCrash.h 中的 onCrash)

如果您想在崩溃发生后进行一些额外的处理(可能向报告添加更多上下文数据),您可以这样做。

但是,您必须确保仅使用异步安全的代码,并且最重要的是永远不要从该方法中调用 Objective-C 代码!在许多情况下,您可以侥幸逃脱,但某些类型的崩溃会导致忽略此警告的处理程序代码崩溃!请注意,如果发生这种情况,KSCrash 将检测到它并编写一份完整的报告,但您的自定义处理程序代码可能无法完全运行。

权衡:自定义崩溃处理代码,但您必须小心放入其中的内容!

KSCrash 日志重定向

这将获取 KSCrash 将打印到控制台的任何内容,并将其写入文件。我主要将此用于调试 KSCrash 本身,但它可能用于其他目的,因此我公开了一个 API。

示例

workspace 包括一些示例应用程序,这些应用程序演示了常见的 KSCrash 用法。请查看每个应用程序中 AppDelegate.m 的顶部,以了解其功能的描述。

许可证

版权所有 (c) 2012 Karl Stenerud

特此授予任何人免费许可,以获得本软件和相关文档文件(“软件”)的副本,以不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件的副本,并允许向提供本软件的人员提供以下条件

以上版权声明和本许可声明应包含在模板文件本身的任何再分发的文档中(但不包含在使用模板构建的项目中)。

本软件按“原样”提供,不作任何明示或暗示的保证,包括但不限于适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为或其他方面,因软件或软件的使用或其他处理而产生、产生或与之相关的责任。