iOS崩溃日志中的异常类型

时间:2011-09-16 15:02:47

标签: iphone objective-c ios exception crash-reports

自从我开始学习iOS开发以来,我见过几种不同类型的崩溃日志。

我知道: 异常类型:EXC_BAD_ACCESS(SIGSEGV)表示我们正在访问已发布的对象。

但不知道:
例外类型:EXC_BAD_ACCESS(SIGBUS)
例外类型:EXC_CRASH(SIGABRT)
例外类型:EXC_BREAKPOINT(SIGTRAP)

你知道iOS崩溃日志中有多少异常类型,它们是什么意思?

4 个答案:

答案 0 :(得分:96)

  

我知道:异常类型:EXC_BAD_ACCESS(SIGSEGV)表示我们正在访问已发布的对象。

SIGSEGV是一个分段错误,这意味着您正在尝试访问无效的内存地址。

这些例外(事实上,它们是信号)与Objective-C无关,但是C. 所以你可以在没有Objective-C对象的情况下得到这样的异常。

请注意,信号不是例外,这意味着您无法通过@try@catch块捕获它们。

您可以使用signalsigaction函数设置信号处理程序。请记住一些信号,如SIGABRT无法阻止。

如果您想了解更多信息,可以查看有关信号的Wikipedia页面。

那说,要恢复:

SIGSEGV (细分错误)

访问无效的内存地址。该地址存在,但您的程序无权访问它。

SIGBUS (总线错误)

访问无效的内存地址。地址不存在,或者对齐无效。

SIGFPE (浮点异常)

无效的算术运算。尽管有名称,但可以与整数运算相关。

SIGPIPE

管道破裂。

SIGILL

非法处理器指令。

SIGTRAP

调试器相关

SIGABRT

程序崩溃,与上述信号之一无关。

答案 1 :(得分:29)

SIGSEGV字面意思是说您正在访问您不拥有的地址。所以你不一定要访问已发布的对象;你可以访问一个从未存在的对象,如:

UIView *view; // uninitialised, could point to anything
[view setFrame:someFrame];

甚至只是在C级非对象内容中出错,例如:

int array[100];
array[1000] = 23; // out-of-bounds access

SIGBUS与SIGSEGV非常相似,不同之处在于硬件级别(通常是尝试访问确实存在但您不拥有的地址并尝试访问后面没有任何内容的地址之间的区别它,但这不是一个严格的定义),但通常与相同类型的错误相关联,尽管SIGBUS更可能与未初始化的变量而不是SIGSEGV。

如果您尝试映射到可能在Objective-C中创建的错误,您可能只想将SIGSEGV和SIGBUS一起读取为“我没有权利进行的内存访问”。

SIGABRT是一个试图中止自己的程序,因此通常意味着某种内部一致性检查失败了。例如,如果您尝试两次释放相同的内存,或者 - 在Cocoa级别 - 如果raise NSException没有被捕获,则会引发SIGABRT。如果你得到一个SIGABRT,你做错了系统软件检测到的东西(与硬件中出现的SEGV和BUS相反)。

SIGTRAP是从程序调用到调试器。有趣的是,当你做错了可以在软件中检测到但与环境有关而不是你的特定代码时,Apple似乎会使用这些。因此,例如,您调用存在于您构建的SDK中但不存在于您运行的设备上的C函数(例如,当您针对具有较低部署目标的最新SDK构建时),或者执行类似的操作一个对象。

答案 2 :(得分:4)

这些消息来自gdb,它们不是objective-C的专有消息。 要获取有关信号的信息,您只需在调试器控制台this is an example output输入info signals即可。很抱歉没有在这里发布,但控制台输出的格式很糟糕。

Source and more info about signals

答案 3 :(得分:1)

我最近研究了这个主题领域,这是我的摘要:

EXC_BAD_ACCESS (SIGSEGV)EXC_BAD_ACCESS (SIGBUS)

我们的程序很可能试图访问错误的内存位置或地址很好,但是我们没有访问它的特权。内存可能由于内存压力而被释放。

EXC_BREAKPOINT (SIGTRAP)

这是由于引发了NSException(可能是由我们代表图书馆提出)或调用了_NSLockErrorobjc_exception_throw。例如,这可能是Swift环境检测到异常,例如强制展开nil可选项。

EXC_BAD_INSTRUCTION (SIGILL)

这是程序代码本身而不是其可能正在访问的内存故障时。这在iOS设备上应该很少见;可能是编译器或优化器错误,或者是错误的手写汇编代码。在Simulator上,情况完全不同,因为使用未定义的操作码是Swift运行时用于停止访问僵尸对象(已分配对象)的一种技术。

EXC_GUARD

这是程序关闭受保护的文件描述符时的情况。一个示例是系统使用的SQLite数据库。