iphone - iOS:如何获取未处理的 std::exception 的堆栈跟踪?

标签 iphone ios ipad crash crash-reports

如果抛出未处理的 NSException,则堆栈跟踪有如下部分:

Last Exception Backtrace:
0   CoreFoundation                  0x32bd688f __exceptionPreprocess + 163
1   libobjc.A.dylib                 0x34b7b259 objc_exception_throw + 33
2   CoreFoundation                  0x32bd65c5 -[NSException init] + 1
3   Foundation                      0x37296bd7 -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 263
...

但是如果抛出 std::exception,我只会得到这个:

Thread 0 Crashed:
0   libsystem_kernel.dylib          0x34f2632c __pthread_kill + 8
1   libsystem_c.dylib               0x31e4c208 pthread_kill + 48
2   libsystem_c.dylib               0x31e45298 abort + 88
3   libc++abi.dylib                 0x33bcaf64 abort_message + 40
4   libc++abi.dylib                 0x33bc8346 default_terminate() + 18
5   libobjc.A.dylib                 0x349f4368 _objc_terminate + 164
6   libc++abi.dylib                 0x33bc83be safe_handler_caller(void (*)()) + 70
7   libc++abi.dylib                 0x33bc844a std::terminate() + 14
8   libc++abi.dylib                 0x33bc981e __cxa_rethrow + 82
9   libobjc.A.dylib                 0x349f42a2 objc_exception_rethrow + 6
10  CoreFoundation                  0x329a5506 CFRunLoopRunSpecific + 398
11  CoreFoundation                  0x329a5366 CFRunLoopRunInMode + 98
12  GraphicsServices                0x32af2432 GSEventRunModal + 130
13  UIKit                           0x34f84cce UIApplicationMain + 1074
14  APP_NAME                            0x00086b10 main (main.m:68)
15  APP_NAME                        0x00071b98 start + 32

如何从这个崩溃日志中获取准确的崩溃信息?

更新--

我试过 HockeyApp,但它与 iTunes 崩溃日志有相同的限制 - 它没有告诉我未处理的 C++ 异常的堆栈。

最佳答案

您看到的是 AppKit 和 UIKit 的一个不幸的怪癖。 iOS 和 OS X 在 CFRunLoop 中都有一个异常处理程序,用于捕获所有未捕获的异常。在 OS X 上,处理程序通过对话框向用户显示异常,但在 iOS 上,处理程序只是重新抛出异常。

Objective-C 异常,由 NSException 实现,在实际“抛出”发生之前将它们的回溯保存在异常对象中,作为 [NSException init] 的一部分(或类似的初始化方法)。不幸的是,C++ 异常不会做同样的事情。通常,C++ 异常具有回溯,因为运行时库检测到没有 catch 并立即调用 std::terminate,后者又调用 abort(),保持整个调用堆栈完好无损,如下所示:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff93ef8d46 __kill + 10
1   libsystem_c.dylib               0x00007fff89968df0 abort + 177
2   libc++abi.dylib                 0x00007fff8beb5a17 abort_message + 257
3   libc++abi.dylib                 0x00007fff8beb33c6 default_terminate() + 28
4   libobjc.A.dylib                 0x00007fff8a196887 _objc_terminate() + 111
5   libc++abi.dylib                 0x00007fff8beb33f5 safe_handler_caller(void (*)()) + 8
6   libc++abi.dylib                 0x00007fff8beb3450 std::terminate() + 16
7   libc++abi.dylib                 0x00007fff8beb45b7 __cxa_throw + 111
8   test                            0x0000000102999f3b main + 75
9   libdyld.dylib                   0x00007fff8e4ab7e1 start + 1

但是,当运行循环异常处理程序捕获异常时,执行会在 catch block 内正常恢复。原始回溯因此丢失。重新抛出随后调用 std::terminate,但此时,调用堆栈反射(reflect)了运行循环异常处理程序。

在这种情况下,要从 C++ 异常中获取回溯,您必须抛出一个模拟 NSException 的异常对象,并将调用堆栈作为其构造函数的一部分读取,并确保抛出所有异常在你的代码中做同样的事情。 std::exception 不会这样做,而且您使用的任何第三方代码也不太可能这样做。

向 Apple 提交一个错误,要求他们删除 CFRunLoop 异常处理程序,或者至少提供一个 API 来关闭它。目前没有用于执行此操作的 API,甚至没有 SPI。

关于iphone - iOS:如何获取未处理的 std::exception 的堆栈跟踪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13777446/

相关文章:

ios - iOS 8.1仅间歇性显示UITextView

ios - Apple 的服务器端 Swift 框架

ios - Get Array With Array 但它是数组中的数组

ios - 由于弹出窗口,在 iPad 上测试时应用程序崩溃

ios - 为 ui 组件提供绝对值 - 不适用于 iPad

iphone - MonoTouch : UpPopoverController. DidDismiss 未触发

android - 通话过程如何与蓝牙设备配合使用?

iphone - iPhone 上的 FTP 与 HTTP 上传

iphone - 关于 iAd 在 iPad 和 iPhone 上显示的问题

iphone - UIScrollView 不弹起