【NDK系列】Android tombstone文件分析

2024-03-03 07:52

本文主要是介绍【NDK系列】Android tombstone文件分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文件位置

data/tombstone/tombstone_xx.txt

获取tombstone文件命令:

  1. adb shell cp /data/tombstones ./tombstones

触发时机

NDK程序在发生崩溃时,它会在路径/data/tombstones/下产生导致程序crash的文件tombstone_xx,记录了死亡了进程的基本信息(例如进程的进程号,线程号),死亡的地址(在哪个地址上发生了Crash),死亡时的现场是什么样的(记录了一系列的堆栈调用信息)等等。

内容示例

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android-x86/android_x86/x86:5.1.1/LMY48W/woshijpf04211939:eng/test-keys'
Revision: '0'
ABI: 'x86'
pid: 1019, tid: 1019, name: surfaceflinger  >>> /system/bin/surfaceflinger <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4eax a6265c06  ebx b7467d88  ecx b7631a22  edx a6265c06esi 00000000  edi b6867140xcs 00000073  xds 0000007b  xes 0000007b  xfs 00000000  xss 0000007beip b745a639  ebp bfcfc1e8  esp bfcfc150  flags 00010282backtrace:#00 pc 00006639  /system/lib/libui.so (android::Fence::waitForever(char const*)+41)#01 pc 00034b86  /system/lib/libsurfaceflinger.so#02 pc 0003229e  /system/lib/libsurfaceflinger.so#03 pc 0002cb9c  /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+652)#04 pc 000342f4  /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+2580)#05 pc 0004eafb  /system/lib/libgui.so (android::Surface::queueBuffer(ANativeWindowBuffer*, int)+411)#06 pc 0004ce06  /system/lib/libgui.so (android::Surface::hook_queueBuffer(ANativeWindow*, ANativeWindowBuffer*, int)+38)#07 pc 00014bc6  /system/lib/egl/libGLES_android.so#08 pc 00017f73  /system/lib/egl/libGLES_android.so (eglSwapBuffers+163)#09 pc 00015fdb  /system/lib/libEGL.so (eglSwapBuffers+203)#10 pc 000013ea  /system/lib/hw/hwcomposer.x86.so#11 pc 00034730  /system/lib/libsurfaceflinger.so#12 pc 000256d4  /system/lib/libsurfaceflinger.so#13 pc 00024bf4  /system/lib/libsurfaceflinger.so#14 pc 000236fb  /system/lib/libsurfaceflinger.so#15 pc 0002338a  /system/lib/libsurfaceflinger.so#16 pc 0001e0ff  /system/lib/libsurfaceflinger.so#17 pc 0001d9ce  /system/lib/libutils.so (android::Looper::pollInner(int)+926)#18 pc 0001db73  /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+67)#19 pc 0001e561  /system/lib/libsurfaceflinger.so#20 pc 00022ce7  /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::run()+39)#21 pc 00000ca3  /system/bin/surfaceflinger#22 pc 0001365a  /system/lib/libc.so (__libc_init+106)#23 pc 00000da8  /system/bin/surfaceflingerstack:bfcfc110  00000000  bfcfc114  b6839270  bfcfc118  00000000  bfcfc11c  00000000  bfcfc120  b68394e0  bfcfc124  00000002  bfcfc128  00000002  bfcfc12c  b75d8185  /system/lib/libutils.so (android::RefBase::incStrong(void const*) const+53)bfcfc130  b6839270  bfcfc134  bfcfc1e8  [stack]bfcfc138  00000002  bfcfc13c  a6265c06  bfcfc140  b7467d88  /system/lib/libui.sobfcfc144  00000000  bfcfc148  b6867140  bfcfc14c  b745a639  /system/lib/libui.so (android::Fence::waitForever(char const*)+41)#00  bfcfc150  b683af18  bfcfc154  bfcfc1e8  [stack]bfcfc158  00000000  bfcfc15c  00000000  bfcfc160  00000000  bfcfc164  b683af18  bfcfc168  b75ec9c4  /system/lib/libutils.sobfcfc16c  b75d8285  /system/lib/libutils.so (android::RefBase::weakref_type::decWeak(void const*)+37)bfcfc170  00000000  bfcfc174  00000000  bfcfc178  00000000  bfcfc17c  00000000  bfcfc180  b7642968  /system/lib/libsurfaceflinger.sobfcfc184  bfcfc1e8  [stack]bfcfc188  b6867140  bfcfc18c  b7622b87  /system/lib/libsurfaceflinger.so

构建指纹

Build fingerprint: 'Android-x86/android_x86/x86:5.1.1/LMY48W/woshijpf04211939:eng/test-keys'

典型的格式为:AOSP/[Android Version]/[Build ID]/[Build Date]

  • “Android-x86”: 表示Android-x86工程
  • “android_x86”: 表示Android-x86工程的分支名或者构建变体
  • “x86:5.1.1”: 表示安卓版本为5.1.1, 即Lollipop。"x86"表示其针对x86架构CPU进行优化
  • “LMY48W”: 表示构建号(build number),构建号可以自定义,比如某个feature、bugfix的提交号
  • “woshijpf04211939:eng”: 自定义标签,比如构建者、构建目等,“eng” 可能表示使用了engineering配置
  • “test-keys”: 表示此构建使用了测试key而不是正式发布的key文件

崩溃的过程和PID

pid: 1019, tid: 1019, name: surfaceflinger  >>> /system/bin/surfaceflinger <<<

如果pid等于tid,那么就说明这个程序是在主线程中Crash掉的,名称的属性则表示Crash进程的名称以及在文件系统中位置。

终止信号和故障地址

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4

信息说明出现进程Crash的原因是因为程序产生了段错误的信号,访问了非法的内存空间,而访问的非法地址是0x4。

典型的内存地址访问错误:

  1. 野指针
  2. 内存泄露
  3. 堆栈溢出
  4. 初始化错误
  5. 类型转换错误
  6. 数字除0

Linux信号机制

崩溃信号列表

在这里插入图片描述
信号机制是Linux进程间通信的一种重要方式,Linux信号一方面用于正常的进程间通信和同步,如任务控制(SIGINT,SIGTSTP,SIGKILL,SIGCONT,…);另一方面,它还负责监控系统异常及中断。当应用程序运行异常时,Linux内核将产生错误信号并通知当前进程。当前进程在接收到该错误信号后,可以有三种不同的处理方式:

  1. 忽略该信号。
  2. 捕捉该信号并执行对应的信号处理函数(信号处理程序)。
  3. 执行该信号的缺省操作(如SIGSEGV,其缺省操作是终止进程)。

当Linux应用程序在执行时发生严重错误,一般会导致程序崩溃。其中,Linux专门提供了一类crash信号,在程序接收到此类信号时,缺省操作是将崩溃的现场信息记录到核心文件,然后终止进程。

CPU寄存器

调用堆栈

backtrace:#00 pc 00006639  /system/lib/libui.so (android::Fence::waitForever(char const*)+41)#01 pc 00034b86  /system/lib/libsurfaceflinger.so#02 pc 0003229e  /system/lib/libsurfaceflinger.so#03 pc 0002cb9c  /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+652)#04 pc 000342f4  /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+2580)
  • #00,#01,#02表示函数调用栈中栈帧的编号,编号越小的栈帧表示着当前最近调用的函数信息,所以栈帧标号#00表示的就是当前正在执行并导致程序崩溃函数的信息。
  • pc后面的16进制数值表示的是当前函数正在执行的语句在共享链接库或者可执行文件中的位置
  • /system/lib/libui.so表示的是当前执行指令是在哪个文件当中
  • 小括号则是注明对应的是哪个函数
    例如,在上面的例子中,我们就可以定位到是程序是在Fence :: waitForever(char const *)中出现了错误,但是具体在那一行呢,我们还不是特别清楚,所以就需要我们进一步地使用更加高级的工具来帮助我们解析tombstone中有关调用栈的信息。

堆叠每个通话的内容

处理工具

Google在NDK包中为我们提供了一系列的调试工具:

  • addr2line
  • objdump
  • ndk-stack

在介绍上述工具的使用方法之前有必要再次介绍一下so文件的构成,虽然这部分内容属于NDK范畴。

so文件介绍

so文件组成

完整的 .so 文件由 C/C++代码和一些 debug 信息组成,这些 debug 信息会记录 .so中所有方法的对照表,就是方法名和其偏移地址的对应表,也叫做符号表symbolic 信息,这种.so被称为未strip的,通常体积会比较大。

注意:

  1. 符号表可以类比为 Java 代码混淆中的 mapping 文件,只有拥有这个 mapping 文件才能进行堆栈分析。
  2. 编译完so文件后,需要保留「机器码+debug信息的完整so文件」或者「仅含debug信息的符号表文件」

在这里插入图片描述

可以通过file命令查看so文件基本信息,以判断是否包含debug信息:

# 查看已被stripped的so文件
file libbreakpad-core-s.so
libbreakpad-core-s.so: *******, BuildID[sha1]=54ad86d708f4dc0926ad220b098d2a9e71da235a, stripped
# 查看未被stripped的so文件
file libbreakpad-core.so
libbreakpad-core.so: ******, BuildID[sha1]=54ad86d708f4dc0926ad220b098d2a9e71da235a, with debug_info, not stripped

so文件获取

目前 Android Studio 无论是使用 mk 或者 Cmake 编译的方式都会同时输出 strip 和未 strip 的 so:

  • strip 之前的 so 路径:{project}/app/build/intermediates/merged_native_libs
  • strip 之后的 so 路径:{project}/app/build/intermediates/stripped_native_libs

如下图是 Cmake 编译 so 产生的两个对应的 so:

图片 1 图片 2

addr2line

该工具通过输入so文件和backtrace中的地址来输出源码中的行号,支持一次性输入多个地址。

工具路径:

  • Mac OS:$NDK_ROOT/toolchains/x86-4.9/prebuilt/darwin-x86_64/bin/i686-linux-android-addr2line

最佳实践:

alias addr2line='$NDK_HOME/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android-addr2line'

注意:

  1. so文件需要带符号表,位于out/target/product/cc_company/symbols/system/lib
  2. 由于是逐行解析,因此想要得到完整的源码调用栈需要自行封装写个脚本工具;

用法

Usage:android-addr2line [option(s)] [addr(s)]Convert addresses into line number/file name pairs.If no addresses are specified on the command line, they will be read from stdinThe options are:@<file>                Read options from <file>-a --addresses         Show addresses-b --target=<bfdname>  Set the binary file format-e --exe=<executable>  Set the input file name (default is a.out)-i --inlines           Unwind inlined functions-j --section=<name>    Read section-relative offsets instead of addresses-p --pretty-print      Make the output easier to read for humans-s --basenames         Strip directory names-f --functions         Show function names-C --demangle[=style]  Demangle function names-h --help              Display this information-v --version           Display the program's versionandroid-addr2line: supported targets: elf32-i386 elf32-iamcu a.out-i386-linux pei-i386 elf64-x86-64 elf32-x86-64 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big plugin srec symbolsrec verilog tekhex binary ihex
Report bugs to <http://www.sourceware.org/bugzilla/>

推荐:add2line -fCp -e /path/to/xxx.so \<addresses\>

示例

执行命令:
addr2line -f -e libui.so 00006639

输出结果:

_ZN7android5Fence11waitForeverEPKc
/home/woshijpf/newspace/android-x86/frameworks/native/libs/ui/Fence.cpp:59

ndk-stack

可将墓碑文件中的backtrace和stack完整还原成源码文件路径+代码行号的呈现方式。

工具路径:$NDK_HOME/ndk-stack

注意:

  1. 需要obj目录,例如obj/local/x86/
  2. 通常用于本地调试阶段的问题排查,对于线上问题排查时不一定保留这些符号表文件

用法

Usage:ndk-stack -sym <path> [-dump <path>]-sym  Contains full path to the root directory for symbols.-dump Contains full path to the file containing the crash dump.This is an optional parameter. If ommited, ndk-stack willread input data from stdin
  • sym: 需要输入符号表文件的根目录,即obj目录
  • dump:输入指定的trace文本文件路径或者若缺省则从标准输入读取

示例

原墓碑文件内容:

// tombstone_01 文件内容
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android-x86/android_x86/x86:5.1.1/LMY48W/woshijpf04211939:eng/test-keys'
Revision: '0'
ABI: 'x86'
pid: 2125, tid: 2125, name: androidvncserve  >>> androidvncserver <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0eax 00000000  ebx b76ffff4  ecx b6a37000  edx 00000000esi 00000000  edi 00000000xcs 00000073  xds 0000007b  xes 0000007b  xfs 00000000  xss 0000007beip b75a4ec5  ebp bfa9bd08  esp bfa9bbf0  flags 00010246backtrace:#00 pc 0004bec5  /system/bin/androidvncserver#01 pc 0004e3e4  /system/bin/androidvncserver#02 pc 0001365a  /system/lib/libc.so (__libc_init+106)#03 pc 0001060c  /system/bin/androidvncserverstack:bfa9bbb0  bfa9bbc8  [stack]bfa9bbb4  b72c6fb0  /system/lib/libdvnc_flinger_sdk22.sobfa9bbb8  b72c7004  /system/lib/libdvnc_flinger_sdk22.sobfa9bbbc  b72c5b26  /system/lib/libdvnc_flinger_sdk22.so (readfb_flinger+38)bfa9bbc0  b68ae080  bfa9bbc4  00000000  bfa9bbc8  00000000  bfa9bbcc  00000000  bfa9bbd0  00000000  bfa9bbd4  b76ffff4  /system/bin/androidvncserverbfa9bbd8  b76a5e20  /system/bin/androidvncserverbfa9bbdc  b75ac181  /system/bin/androidvncserverbfa9bbe0  b75ac16b  /system/bin/androidvncserverbfa9bbe4  b76ffff4  /system/bin/androidvncserverbfa9bbe8  bfa9bd08  [stack]bfa9bbec  b75a579b  /system/bin/androidvncserver#00  bfa9bbf0  00000012  bfa9bbf4  bfa9bc1c  [stack]bfa9bbf8  00000000  bfa9bbfc  00000000  bfa9bc00  bfa9bc14  [stack]bfa9bc04  00000000  bfa9bc08  00000000  bfa9bc0c  b7498825  /system/lib/libc.so (je_free+453)bfa9bc10  0000000e  bfa9bc14  00000400  bfa9bc18  00000000  bfa9bc1c  b749538a  /system/lib/libc.so (je_malloc+778)bfa9bc20  0000000c  bfa9bc24  00000065  bfa9bc28  00000000  bfa9bc2c  b6a37000  ........  ........#01  bfa9bd10  b6bb7300  bfa9bd14  00001b58  bfa9bd18  b76aa954  /system/bin/androidvncserverbfa9bd1c  0000000b  bfa9bd20  00000005  bfa9bd24  00000000  bfa9bd28  00000000  bfa9bd2c  00000005  bfa9bd30  00000006  bfa9bd34  00000005  bfa9bd38  00000000  bfa9bd3c  00000000  bfa9bd40  00000000  bfa9bd44  bfa9bd24  [stack]bfa9bd48  b754f9c8  /system/bin/linkerbfa9bd4c  b7557bd8  /system/bin/linker........  ........#02  bfa9bed0  00000001  bfa9bed4  bfa9bf14  [stack]bfa9bed8  bfa9bf1c  [stack]bfa9bedc  00000000  bfa9bee0  b7556fec  /system/bin/linkerbfa9bee4  bfa9bf10  [stack]bfa9bee8  00000000  bfa9beec  b7556fec  /system/bin/linkerbfa9bef0  bfa9bf10  [stack]bfa9bef4  00000000  bfa9bef8  bfa9bf0c  [stack]bfa9befc  b756960d  /system/bin/androidvncserver#03  bfa9bf00  bfa9bf10  [stack]bfa9bf04  00000000  bfa9bf08  b756960d  /system/bin/androidvncserverbfa9bf0c  b7569612  /system/bin/androidvncserverbfa9bf10  00000001  bfa9bf14  bfa9cb05  [stack]bfa9bf18  00000000  bfa9bf1c  bfa9cb16  [stack]bfa9bf20  bfa9cb35  [stack]bfa9bf24  bfa9cb48  [stack]bfa9bf28  bfa9cba3  [stack]bfa9bf2c  bfa9cbae  [stack]bfa9bf30  bfa9cbc1  [stack]bfa9bf34  bfa9cbdc  [stack]bfa9bf38  bfa9cbe7  [stack]bfa9bf3c  bfa9cbfd  [stack]

执行命令:
ndk-stack -sym obj/local/x86/ -dump ~/android-x86-debug-log/tombstone_01

输出结果:

********** Crash dump: **********
Build fingerprint: 'Android-x86/android_x86/x86:5.1.1/LMY48W/woshijpf04211939:eng/test-keys'
pid: 2125, tid: 2125, name: androidvncserve  >>> androidvncserver <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
Stack frame #00 pc 0004bec5  /system/bin/androidvncserver: Routine update_screen_16 in /home/woshijpf/android_workspace/droidVNCserver-real/jni/vnc/updateScreen.c:68
Stack frame #01 pc 0004e3e4  /system/bin/androidvncserver: Routine main in /home/woshijpf/android_workspace/droidVNCserver-real/jni/vnc/droidvncserver.c:805
Stack frame #02 pc 0001365a  /system/lib/libc.so (__libc_init+106)
Stack frame #03 pc 0001060c  /system/bin/androidvncserver: Unable to locate routine information for address 1060c in module obj/local/x86//androidvncserver
Stack frame #00 pc 0007bf71  /system/lib/libc.so (nanosleep+17)
Stack frame #01 pc 00047ed6  /system/lib/libc.so (usleep+70)
Stack frame #02 pc 0004fa6b  /system/bin/androidvncserver: Routine camera_io in /home/woshijpf/android_workspace/droidVNCserver-real/jni/vnc/camera_io.c:557
Stack frame #03 pc 0004af6a  /system/bin/androidvncserver: Routine receive_camera in /home/woshijpf/android_workspace/droidVNCserver-real/jni/vnc/droidvncserver.c:273
Stack frame #04 pc 00022168  /system/lib/libc.so (__pthread_start(void*)+56)
Stack frame #05 pc 0001cc69  /system/lib/libc.so (__start_thread+25)
Stack frame #06 pc 000137c6  /system/lib/libc.so (__bionic_clone+70)
Stack frame #00 pc 0007cc33  /system/lib/libc.so (recvfrom+19)
Stack frame #01 pc 00050cdb  /system/bin/androidvncserver: Routine handle_connections in /home/woshijpf/android_workspace/droidVNCserver-real/jni/vnc/gui.c:105
Stack frame #02 pc 00022168  /system/lib/libc.so (__pthread_start(void*)+56)
Stack frame #03 pc 0001cc69  /system/lib/libc.so (__start_thread+25)
Stack frame #04 pc 000137c6  /system/lib/libc.so (__bionic_clone+70)

objdump

使用objdump命令对目标文件(obj)或可执行文件进行反汇编,它以一种可阅读的格式让你更多的了解二进制文件可能带有的附加信息。

参考文章:objdump的使用

参考资料

  • 谷歌官方教程:调试 Android 平台原生代码
  • Android NDK墓碑/崩溃分析_android墓碑文件_Lixby的博客-CSDN博客
  • Android的墓碑 - 掘金
  • Android 平台 Native Crash 问题分析与定位

这篇关于【NDK系列】Android tombstone文件分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/768971

相关文章

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原