log信息signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr
。代码中Abort中止操作为刻意为之。执行中止操作可通过多种不同的方法(包括调用 abort(3)、使 assert(3) 失败、使用 Android 特有的严重记录类型)来实现,所有方法都调用到 abort。abort 调用会向发起调用的线程发出 SIGABRT 信号,因此在log中,libc.so 中显示“abort”的帧,以及 SIGABRT 信号。
参考示例如下(部分日志):
pid: 4637, tid: 4637, name: crasher >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: ‘some_file.c:123: some_function: assertion “false” failed’
r0 00000000 r1 0000121d r2 00000006 r3 00000008
r4 0000121d r5 0000121d r6 ffb44a1c r7 0000010c
r8 00000000 r9 00000000 r10 00000000 r11 00000000
ip ffb44c20 sp ffb44a08 lr eace2b0b pc eace2b16
backtrace:
#00 pc 0001cb16 /system/lib/libc.so (abort+57)
#01 pc 0001cd8f /system/lib/libc.so (__assert2+22)
#02 pc 00001531 /system/bin/crasher (do_action+764)
#03 pc 00002301 /system/bin/crasher (main+68)
#04 pc 0008a809 /system/lib/libc.so (__libc_init+48)
#05 pc 00001097 /system/bin/crasher (_start_main+38)
···中止相关代码信息省略
在log中一般会看到明确的中止信息,了解此线程在刻意终止自身之前所记录的内容。追踪Native调用栈,返回追查定位问题。
android系统native层代码中存在一些判断逻辑进行abort,不一定是native层的问题,可能存在上层App触发了错误的逻辑。
分为纯空指针和低地址空指针,log信息为signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
。
纯空指针引用示例如下:
pid: 25326, tid: 25326, name: crasher >>> crasher <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
r0 00000000 r1 00000000 r2 00004c00 r3 00000000
r4 ab088071 r5 fff92b34 r6 00000002 r7 fff92b40
r8 00000000 r9 00000000 sl 00000000 fp fff92b2c
ip ab08cfc4 sp fff92a08 lr ab087a93 pc efb78988 cpsr 600d0030
backtrace:
#00 pc 00019988 /system/lib/libc.so (strlen+71)
#01 pc 00001a8f /system/xbin/crasher (strlen_null+22)
#02 pc 000017cd /system/xbin/crasher (do_action+948)
#03 pc 000020d5 /system/xbin/crasher (main+100)
#04 pc 000177a1 /system/lib/libc.so (__libc_init+48)
#05 pc 000010e4 /system/xbin/crasher (_start+96)
在上面示例中,尽管崩溃函数在 libc.so 内,但由于字符串函数仅在指定给它们的指针处进行操作,因此您可以推断出在调用 strlen(3) 时指定的是 Null 指针;对于这类崩溃问题,应直接找发起调用的代码的作者加以解决。在这种情况下,帧 #01 是不良调用程序。
*低地址 Null 空指针引用和更多信号奔溃问题详见:诊断原生代码崩溃问题。
Arch Linux发行版中,有着arch/usr/include/asm/signal.h这样的头文件,定义Linux系统中信号类型。Linux中32个信号及其含义如下:
信号 | 含义 |
---|---|
#define SIGHUP 1 | 终端挂起或控制进程终止 |
#define SIGINT 2 | 终端中断(Ctrl+C 组合键) |
#define SIGQUIT 3 | 终端退出(Ctrl+\组合键) |
#define SIGILL 4 | 非法指令 |
#define SIGTRAP 5 | debug 使用,有断点指令产生 |
#define SIGABRT 6 | 由 abort(3)发出的退出指令 |
#define SIGIOT 6 | IOT 指令 |
#define SIGBUS 7 | 总线错误 |
#define SIGFPE 8 | 浮点运算错误 |
#define SIGKILL 9 | 杀死、终止进程 |
#define SIGUSR1 10 | 用户自定义信号 1 |
#define SIGSEGV 11 | 段违例(无效的内存段) |
#define SIGUSR2 12 | 用户自定义信号 2 |
#define SIGPIPE 13 | 向非读管道写入数据 |
#define SIGALRM 14 | 闹钟 |
#define SIGTERM 15 | 软件终止 |
#define SIGSTKFLT 16 | 栈异常 |
#define SIGCHLD 17 | 子进程结束 |
#define SIGCONT 18 | 进程继续 |
#define SIGSTOP 19 | 停止进程的执行,只是暂停 |
#define SIGTSTP 20 | 停止进程的运行(Ctrl+Z 组合键) |
#define SIGTTIN 21 | 后台进程需要从终端读取数据 |
#define SIGTTOU 22 | 后台进程需要向终端写数据 |
#define SIGURG 23 | 有"紧急"数据 |
#define SIGXCPU 24 | 超过 CPU 资源限制 |
#define SIGXFSZ 25 | 文件大小超额 |
#define SIGVTALRM 26 | 虚拟时钟信号 |
#define SIGPROF 27 | 时钟信号描述 |
#define SIGWINCH 28 | 窗口大小改变 |
#define SIGIO 29 | 可以进行输入/输出操作 |
#define SIGPOLL | SIGIO |
#define SIGPWR 30 | 断点重启 |
#define SIGSYS 31 | 非法的系统调用 |
#define SIGUNUSED 32 | 未使用信号 |
参考博客:Linux中32个信号及其含义或Android native crash 信号量signal对应的含义。
32种信号同样适用于Android系统。