如何阅读崩溃日志?如何找到应用程序在系统库中崩溃的原因?什么是EXC_CRASH(SIGABRT)?

7
我收到一位客户的崩溃日志,想找出为什么我的应用程序在她的iPhone上崩溃的原因。以下是来自崩溃日志的一些信息:
异常类型:EXC_CRASH(SIGABRT) 异常代码:0x00000000、0x00000000 崩溃线程:0
线程0的堆栈跟踪:
Thread 0 Crashed: 0 libSystem.B.dylib 0x3293f98c 0x328c1000 + 518540 1 libSystem.B.dylib 0x3293f97c 0x328c1000 + 518524 2 libSystem.B.dylib 0x3293f96e 0x328c1000 + 518510 3 libSystem.B.dylib 0x3295461a 0x328c1000 + 603674 4 libstdc++.6.dylib 0x30a143b0 0x309cf000 + 283568 5 libobjc.A.dylib 0x3347a858 0x33475000 + 22616 6 libstdc++.6.dylib 0x30a12776 0x309cf000 + 276342 7 libstdc++.6.dylib 0x30a127ca 0x309cf000 + 276426 8 libstdc++.6.dylib 0x30a12896 0x309cf000 + 276630 9 libobjc.A.dylib 0x33479714 0x33475000 + 18196 10 CoreFoundation 0x335c8210 0x33534000 + 606736 11 CoreFoundation 0x3354ea8e 0x33534000 + 109198 12 CoreFoundation 0x33545ab8 0x33534000 + 72376 13 Journaler Lite 0x0001699e -[AccountManager unsignedIntegerValueForPath:](AccountManager.m:151) ...
这是来自AccountManager.m的代码:
NSNumber *number = ...; if (number) { return [number unsignedIntegerValue]; // line 151 } else { return 0; }
主要问题是如何阅读这样的崩溃日志?应用程序在系统库内部某处崩溃,没有更多的附加信息。有没有什么方法可以找到崩溃原因?
更新: 我在许多论坛帖子中搜索了异常类型为EXC_CRASH(SIGABRT)且崩溃线程堆栈的前几行是以下内容的帖子:
线程0崩溃: 0 libSystem.B.dylib 0x3293f98c 0x328c1000 + 518540 1 libSystem.B.dylib 0x3293f97c 0x328c1000 + 518524 2 libSystem.B.dylib 0x3293f96e 0x328c1000 + 518510 3 libSystem.B.dylib 0x3295461a 0x328c1000 + 603674 4 libstdc++.6.dylib 0x30a143b0 0x309cf000 + 283568 5 libobjc.A.dylib 0x3347a858 0x33475000 + 22616 6 libstdc++.6.dylib 0x30a12776 0x309cf000 + 276342 7 libstdc++.6.dylib 0x30a127ca 0x309cf000 + 276426 8 libstdc++.6.dylib 0x30a12896 0x309cf000 + 276630 9 libobjc.A.dylib 0x33479714 0x33475000 + 18196 10 CoreFoundation 0x335c8210 0x33534000 + 606736 11 CoreFoundation 0x3354ea8e 0x33534000 + 109198
这个异常类型(EXC_CRASH (SIGABRT))是什么意思?
1个回答

5
首先,你需要使用DSYM来符号化崩溃日志以了解发生了什么。您需要拥有应用程序构建时的DSYM文件。DSYM文件允许您从这些内存地址反向映射到可读的代码行。
SIGABRT是当您遇到未处理的异常时得到的信号,例如在只有1个项目的数组中调用[someArray objectAtIndex:2]。或者更常见的是未识别的选择器:[NSArray unsignedIntValue]
请查看此问题中的此崩溃日志。请注意,Foundation中的调用堆栈库与您的代码相同-并且这是一个未识别的选择器。
你的代码是:
NSNumber *num = foo;
if (num)
{
  bar = [num unsignedIntValue];
}

你没有告诉我们的但非常重要的是“foo”里面是什么。你如何分配那个NSNumber?如果它不是NSNumber之外的任何其他对象,那么你的崩溃日志将看起来像你的。

如果你想在编程中真正防御,你可以这样说:

if (num && [num isKindOfClass:[NSNumber class]])

但是,无论你的“foo”是什么,它都应该始终返回一个NSNumber。


如果你仔细查看堆栈跟踪(stacktrace)/回溯(backtrace),你会注意到它已经被符号化了。 - Aleksejs Mjaliks
是的和不是 - 它为您的代码符号化,但您不知道Foundation / etc中发生了什么。我找到了另一篇帖子,可能会对您有所帮助,我已经重新编写了我的答案。 - makdad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接