partone: NDK 使用 addr2line 定位 Fatal signal (SIGSEGV) 错误 part tow:参考partone重点这部分有助于理解 part three:logcat的基本设置与各种用法小结

partone:

NDK 使用 addr2line 定位 Fatal signal (SIGSEGV) 错误

使用NDK编写native code时候,真机常会出现crash的错误。然后logcat就是一片错误堆栈。

////androidJNI print info
#include <android/log.h>
#define LOG_TAG "ORB_SLAM_SYSTEM"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

#define LOG(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__)
02-05 11:35:22.883 18969-18969/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x9
02-05 11:35:22.883 18969-18969/? A/DEBUG:     r0 bd026370  r1 d0db2371  r2 bd026348  r3 00000002
02-05 11:35:22.883 18969-18969/? A/DEBUG:     r4 00000001  r5 c3ad8c10  r6 d0f25308  r7 bd026340
02-05 11:35:22.883 18969-18969/? A/DEBUG:     r8 00000001  r9 ffffffff  sl 00036300  fp 00000000
02-05 11:35:22.883 18969-18969/? A/DEBUG:     ip d0f24460  sp bc18f1e0  lr d0dbd1e9  pc d0dbd1fc  cpsr a0070030
02-05 11:35:22.893 18969-18969/? A/DEBUG: backtrace:
02-05 11:35:22.893 18969-18969/? A/DEBUG:     #00 pc 000341fc  /data/app/com.ntanougat.orbslam2test-1/lib/arm/libORB_SLAM2_EXCUTOR.so (_ZN2cv3Mat6createEiPKii+1275)
02-05 11:35:22.893 18969-18969/? A/DEBUG:     #01 pc 0004ce99  /data/app/com.ntanougat.orbslam2test-1/lib/arm/libORB_SLAM2_EXCUTOR.so (_ZNK2cv12_OutputArray6createENS_5Size_IiEEiibi+1052)
02-05 11:35:22.893 18969-18969/? A/DEBUG:     #02 pc 000ebb61  /data/app/com.ntanougat.orbslam2test-1/lib/arm/libORB_SLAM2.so (_ZN2cv8cvtColorERKNS_11_InputArrayERKNS_12_OutputArrayEii+12504)
02-05 11:35:22.893 18969-18969/? A/DEBUG:     #03 pc 000a3e2b  /data/app/com.ntanougat.orbslam2test-1/lib/arm/libORB_SLAM2.so (_ZN9ORB_SLAM28Tracking18GrabImageMonocularERKN2cv3MatERKd+202)
02-05 11:35:22.893 18969-18969/? A/DEBUG:     #04 pc 0009c573  /data/app/com.ntanougat.orbslam2test-1/lib/arm/libORB_SLAM2.so (_ZN9ORB_SLAM26System14TrackMonocularERKN2cv3MatERKd+194)
02-05 11:35:22.893 18969-18969/? A/DEBUG:     #05 pc 000216b5  /data/app/com.ntanougat.orbslam2test-1/lib/arm/libORB_SLAM2_EXCUTOR.so (Java_com_ntanougat_orbslam2test_NdkHelper_OrbNdkHelper_startCurrentORBForCamera+36)
02-05 11:35:22.893 18969-18969/? A/DEBUG:     #06 pc 003e5d4b  /data/app/com.ntanougat.orbslam2test-1/oat/arm/base.odex (offset 0x3c9000)
曾经一直用log的方式查看揣测错误的代码行数。熟不知这些看似淫乱的错误日志其实就是错误堆栈的相关信息,只需要一个工具转换即可。
  1. android-ndk-r10\toolchains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\bin\arm-linux-androideabi-addr2line 
使用方式很简单

  1. // -f 输出函数名  
  2. // -e 输出错误代码行数和文件路径  
  3. // xxx.so 对应出错的so文件, 在android工程obj目录下  
  4. // addr 是具体的地址  
  5. arm-linux-androideabi-addr2line -f -e xxx.so addr
错误日志中backtracer就是堆栈信息,#00 #01 就是堆栈列表。 #00 就是堆栈顶层就是错误所在地址,pc后面的就是地址00000d5c

  1. arm-linux-androideabi-addr2line -f -e libORB_SLAM2_EXCUTOR.so 000216b5

这样瞬间就能定位错误了

Java_com_ntanougat_orbslam2test_NdkHelper_OrbNdkHelper_startCurrentORBForCamera
/home/sun/AS/OrbSlam2Test/app/src/main/jni/orb_slam2_android_nativefunc_OrbNdkHelper.cpp:133

注意这个so文件是android工程obj目录里面的,而不是libs里面的。obj目录是带有debug信息的库文件,libs的库文件是没有debug信息的,addr2line无法读取源代码信息。如果有认识复制过去的文件那么在这两个地方都是可以的,就不用在意啦。

part tow:参考partone重点这部分有助于理解

有一句话叫做常在河边走,哪有不湿鞋。我们这些研究和开发Android的工程师正应了这句话,相必大家在调试的时候经常会遇到这么个东西吧

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'XXXXXXXXX'
pid: 1658, tid: 13086  >>> system_server <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 64696f7e
 r0 00000000  r1 00000001  r2 ad12d1e8  r3 7373654d
 r4 64696f72  r5 00000406  r6 00974130  r7 40d14008
 r8 4b857b88  r9 4685adb4  10 00974130  fp 4b857ed8
 ip 00000000  sp 4b857b50  lr afd11108  pc ad115ebc  cpsr 20000030
 d0  4040000040000000  d1  0000004200000003
 d2  4e72cd924285e370  d3  00e81fe04b1b64d8
 d4  3fbc71c7009b64d8  d5  3fe999999999999a
 d6  4010000000000000  d7  4000000000000000
 d8  4000000000000000  d9  0000000000000000
 d10 0000000000000000  d11 0000000000000000
 d12 0000000000000000  d13 0000000000000000
 d14 0000000000000000  d15 0000000000000000
 scr 80000012

         #00  pc 000108d8  /system/lib/libc.so
         #01  pc 0003724c  /system/lib/libxvi020.so
         #02  pc 0000ce02  /system/lib/libxvi020.so
         #03  pc 0000d672  /system/lib/libxvi020.so
         #04  pc 00010cce  /system/lib/libxvi020.so
         #05  pc 00004432  /system/lib/libwimax_jni.so
         #06  pc 00011e74  /system/lib/libdvm.so
         #07  pc 0004354a  /system/lib/libdvm.so
         #08  pc 00017088  /system/lib/libdvm.so
         #09  pc 0001c210  /system/lib/libdvm.so
         #10  pc 0001b0f8  /system/lib/libdvm.so
         #11  pc 00059c24  /system/lib/libdvm.so
         #12  pc 00059e3c  /system/lib/libdvm.so
         #13  pc 0004e19e  /system/lib/libdvm.so
         #14  pc 00011b94  /system/lib/libc.so
         #15  pc 0001173c  /system/lib/libc.so


code around pc:
ad115e9c 4620eddc bf00bd70 0001736e 0001734e 
ad115eac 4605b570 447c4c0a f7f44620 e006edc8 
ad115ebc 42ab68e3 68a0d103 f7f42122 6864edd2 
ad115ecc d1f52c00 44784803 edbef7f4 bf00bd70 
ad115edc 00017332 00017312 2100b51f 46682210 

code around lr:
afd110e8 e2166903 1a000018 e5945000 e1a02004 
afd110f8 e2055a02 e1a00005 e3851001 ebffed92 
afd11108 e3500000 13856002 1a000001 ea000009 
afd11118 ebfffe50 e1a01004 e1a00006 ebffed92 
afd11128 e1a01005 e1550000 e1a02006 e3a03000 


stack:
    4b857b10  40e43be8  
    4b857b14  00857280  
    4b857b18  00000000  
    4b857b1c  034e8968  
    4b857b20  ad118ce9  /system/lib/libnativehelper.so
    4b857b24  00000002  
    4b857b28  00000406

    .....     

    初一看到直接崩溃,我的个妈,这么一大坨,啥玩意啊,完全搞不懂,没有头绪撒。这NND Android出了问题,冒出这么大堆的地址,搞毛呢。

   其实, 我可以很负责任的告诉你,兄弟这么多其实我也看不懂,在我眼里除了红色和蓝色的地方,其他全是废话。因为除了这两个地方意外,其他的我确实看不懂,一堆线性地址,外加寄存器,跟火星文一样。

   算了,废话不多少,直接分析:

   1 红色的地方,是让我们确认问题到底发生在那个线程中,是主线程还是子线程,这个的判断依据是:如果PID和TID相同,恭喜你问题出在父亲这边,看样子问题还比较好办。如果PID和TID不相同,那么您悲剧了,问题出在子线程中。根据我的经验,100的tombstone中,问题出现在父线程的概率,我还从来没发现,尤其是什么system_server, zygote这些,基本都是儿子的问题。唉,谁叫父亲英雄,儿狗熊呢。。。

  2 确认了问题的基本点,下面就是开始看蓝色的部分了。

    这个蓝色不分是从#00-->#XX 表面上看是从上往下的增长,其实坑爹啊,它所显示的程序的执行流程,恰恰是从下往上的也就是实际的执行顺序是#XX-->#00。

   所以一开始我们的目的是分析第一个出现问题的动态连接库
   #15  pc 0001173c  /system/lib/libc.so

  a 首先按图索骥,找到你的目标,libc.so这个一般会在你编译完的目标目录下,也就是out/target/product/your_pro/system/lib这个目录下。

  b 一般你如果用的是还像样的linux系统,会有个地址解析的命令addr2line,负责解析动态连接库的(如果你是悲剧,没有这个命令,那好吧, google早就预料到会有象你这样的悲剧人,他们在prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-addr2line,给您准备了个,咋就用这个吧,功能一样,没啥区别)

     addr2line -e -f libc.so 0001173c  红色是你的目标库,绿色是你出问题的地址,看看#15这行

    结果出现:??pthread_create

                     ??:0

    恩,好了问题应该出在这个函数中,认为大功告成了?我,呸,还早呢。这个只是告诉你函数入口,至于具体执行到这个函数的哪个地方挂了,还得再看。

c 找到了是哪个部分出了问题,下面就是开启显微镜,看看谁搞的东东。

   使用objdump -S -D libc.so > deassmble_libc.txt 反汇编下你的动态连接库文件,并且将它写入一个文件中。

   打开这个反汇编过后的重定向文件,在查询的时候输入1173c这个偏移地址,你会看到在茫茫人海中

  00011684 <pthread_create>:
   11684:       e92d4ff0        push    {r4, r5, r6, r7, r8, r9, sl, fp, lr}
   11688:       e24dd01c        sub     sp, sp, #28     ; 0x1c
   1168c:       e1a06001        mov     r6, r1
   11690:       e1a08002        mov     r8, r2
   11694:       e1a09003        mov     r9, r3
   11698:       e3a04001        mov     r4, #1  ; 0x1
   1169c:       e59f521c        ldr     r5, [pc, #540]  ; 118c0 <pthread_create+0x23c>
   116a0:       e58d000c        str     r0, [sp, #12]
   116a4:       eb009a35        bl      37f80 <strncmp+0x20>
   116a8:       e59f2214        ldr     r2, [pc, #532]  ; 118c4 <pthread_create+0x240>
   116ac:       e1a03000        mov     r3, r0
   116b0:       e1a01004        mov     r1, r4
   116b4:       e593c000        ldr     ip, [r3]
   116b8:       e3a0003c        mov     r0, #60 ; 0x3c
   116bc:       e08f3005        add     r3, pc, r5
   116c0:       e7933002        ldr     r3, [r3, r2]
   116c4:       e5834000        str     r4, [r3]
   116c8:       e58dc010        str     ip, [sp, #16]
   116cc:       eb009a3b        bl      37fc0 <strncmp+0x60>
   ...

   1173c:       ebffec2b        bl      c7f0 <__pthread_clone>-->就是他了,对你成功了。

   ...

这个是ARM汇编,需要你翻译成对应的C函数去看,这里我就不做解释了,照着前面的步骤,

对上面中#15-->#00 一共16行慢慢去找,直到找到#00行的问题函数,其实,最后一个#00行的是最重要的(前面不找也行,但是可以多给你提供问题信息,和流程),因为他是第一目击者,也是Crash前的第一现场。所以找到这个函数很重要,假设我们最后经过万里长针发现#00的出错的地方是pXX->member挂了(MD,我经常遇到这种问题)。

那么你可以怀疑两个地方:

1 您的指针是空指针,但是现实与理想总是十万八千里,多数情况下很少出现,而且你分析代码后,也会对自己说怎么可能。绝大多数情况下,从我的经验来讲,很少会有空指针这种低级错误,但是不排除哪个2货出现了这么个问题。如果是这个问题,那么恭喜你,你很幸运。

2 还有就是怀疑越界和内存地址被挤占。就拿我以前的经验,指针不是空,但是根据汇编码看,是访问成员变量挂了,这个地址肯定是被占用了。

   针对第2种比较恶心的情况,就需要你看整个log的流程了,需要你看下主要的mainlog关于出现crash前的动作,看看是哪个孙子占用的,以最近原则为先,从下往上看,唉,说句实在话,李白的一句话可以形容整个过程:"蜀道难,难于上青天啊"。工作量大,而且要细致。我也没什么办法。。。

  还有一种情况,就是内存不够,导致了您的地址被挤占了,出现low memory, no more ...这样的语句,以及大量出现GC_FOR_MALLOC关于GC的东西(如果是少量的,可以忽略,大量的话),呵呵表明你的某个进程在吞噬你的内存,存在内存泄漏。坑爹啊,这个问题,是最难查的,需要你花大量时间,去看内存的变化。一般看内存的情况是

cat /proc/meminfo 

空闲内存=buffer+cache+free这三个字段,Active字段是已经使用的内存,Total不用说,是总的物理内存。(记住 free不高,并不代表你的内存空闲不高,海水不可斗量,需要看全了3个字段的总和才是空闲内存)

如果你想具体跟踪每个进程的内存使用情况,还是在/proc下面,对应了N多的数字文件,那个其实是PID号,进去后cat status可以看到

VMRSS XXXKB就是你当前进程的使用内存量,此外还有一些其他的内存数据,包括页啊等等。。。里面还有很多有用的数据,如果你想跟踪所有的进程的内存情况,推介大家可以看看linux ps命令的源码,看看人家是怎么在/proc下遍历进程,并且提取属性值的。

写个daemon,跟踪一段时间,记录下各进程内存的变化,然后就是通宵的分析。。。。


总之,这类问题,很难定位,也很难解决,需要花时间,精力去分析。但是如果你解了,那么相信所有人对你会刮目相看的。包括你的老板,量变引起质变,请记住。


我还在纠结中啊...分析ing


最后再说几句

stack:

#12 476e5eb8  476e5ed8  
    476e5ebc  476e5ed8  
    476e5ec0  00100000  
    476e5ec4  476e5ed8  
    476e5ec8  acaa4d38  
    476e5ecc  005ec9b0  
    476e5ed0  aca4e1a3  /system/lib/libdvm.so
    476e5ed4  476e5ed8  
#13 476e5ed8  005ec9b0  
    476e5edc  005ecae8  
    476e5ee0  476e5f00  
    476e5ee4  aca4e109  /system/lib/libdvm.so
    476e5ee8  005ec9b0  
    476e5eec  afd11b98  /system/lib/libc.so
#14 476e5ef0  476e5f00  
    476e5ef4  005ecae8  
    476e5ef8  45b29b84  
    476e5efc  afd11740  /system/lib/libc.so
#15 476e5f00  476e5f00  
    476e5f04  005ecae8  
    476e5f08  00000009  
    476e5f0c  00000000  
    476e5f10  00000000  
    476e5f14  005ec9b0  
    476e5f18  00000000  
    476e5f1c  00000000  

红色的部分是基地址+偏移地址

比如afd +11740 这个afd你可以从prelink-linux-arm.map找到每个.so的基地址(比如 libc.so                 0xAFD00000 # [~2M])11740可以从反汇编的文件中找到对应点,但是我不知道这些有什么用。

希望这偏小文章能帮助到大家,大家共同进步,有好的方法也欢迎您一起分享。谢谢!

下面是一个老外的摘录早期存于google论坛的内存分析文章(现在没了),我是在他基础上,又加了一些分析和经验之谈,希望上帝保佑让我早点定位到问题。

Crashlog analysis


简要说明:

android系统中调试Java非常容易,一般遇到错误都在logcat中打印出错时函数的调用关系,
而/system/bin/下的可执行程序或者C库中出错时只看到一些二进制信息,使用gdbserver调试环境搭建又比较复杂。
方法一:
下在介绍一个简单的调试库的方法,当然需要有so库的源代码
举例a)         错误信息如下,它表示了出错时的函数调用关系(下面调上面

I/DEBUG   (  634):          #00  pc 000078e6  /system/lib/libmultiplayerservice.so
I/DEBUG   (  634):          #01  pc 000087bc  /system/lib/libmultiplayerservice.so
I/DEBUG   (  634):          #02  pc 0000e94e  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #03  pc 0000a790  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #04  pc 0000d4b2  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #05  pc 0000d852  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #06  pc 00015ece  /system/lib/libutils.so
I/DEBUG   (  634):          #07  pc 0000153a  /system/lib/libsystem_server.so
I/DEBUG   (  634):          #08  pc 00001756  /system/lib/libsystem_server.so
I/DEBUG   (  634):          #09  pc 0000adb8  /system/lib/libandroid_servers.so
I/DEBUG   (  634):          #10  pc 00011cb4  /system/lib/libdvm.so


b)进入源码中带符号表的so库所在目录
$ cd out/target/product/generic/obj/SHARED_LIBRARIES/libmultiplayerservice_intermediates/LINKED

这个有个需要注意的地方:

对于可执行程序及动态库,一般在LINKED子目录中是带有符号的库(没有经过符号剥离),在symbols子目录有带符号的可执行程序,如果可执行文件中没有包括调试符号,您将获得??:0 作为响应。
c)用addr2line命令找到地址对应的程序位置,动态库为libmultiplayerservice.so
arm-eabi-addr2line 000078e6 -e libmultiplayerservice.so
结果:,显示出对应的程序文件和行数,如果不是debug版本,可能有一两行偏差
frameworks/base/services/multiplayerservice/PlayerSocket.cpp 421 行
d)注意
arm-eabi_addr2line在prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin目录下,
运行build/envsetup.sh后即可直接使用它,同目录下的objdump, nm也是常用调试命令

方法二:

1、首先需要一个重要的脚本文件:

#!/usr/bin/python
# stack symbol parser
import os
import string
import sys

#define android product name
ANDROID_PRODUCT_NAME = 'rk3066'

ANDROID_WORKSPACE = os.getcwd()+"/"

# addr2line tool path and symbol path
addr2line_tool = ANDROID_WORKSPACE + 'prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/arm-linux-androideabi-addr2line'
symbol_dir = ANDROID_WORKSPACE + 'out/target/product/' + ANDROID_PRODUCT_NAME +'/symbols'
symbol_bin = symbol_dir + '/system/bin/'
symbol_lib = symbol_dir + '/system/lib/'

class ReadLog:
    def __init__(self,filename):
        self.logname = filename
    def parse(self):
        f = file(self.logname,'r')
        lines = f.readlines()
        if lines != []:
            print 'read file ok'
        else:
            print 'read file failed'
        result =[]
        for line in lines:
            if line.find('stack') != -1:
                print 'stop search'
                break
            elif line.find('system') != -1:
                #print 'find one item' + line
                result.append(line)
        return result

class ParseContent:
    def __init__(self,addr,lib):
            self.address = addr # pc address
            self.exename = lib  # executable or shared library
    def addr2line(self):
        cmd = addr2line_tool + " -C -f -s -e " + symbol_dir + self.exename + " " + self.address
        #print cmd
        stream = os.popen(cmd)
        lines = stream.readlines();
        list = map(string.strip,lines)
        return list
    
inputarg = sys.argv
if len(inputarg) < 2:
    print 'Please input panic log'
    exit()

filename = inputarg[1]
readlog = ReadLog(filename)
inputlist = readlog.parse()

for item in inputlist:
    itemsplit = item.split()
    test = ParseContent(itemsplit[-2],itemsplit[-1])
    list = test.addr2line()
    print "%-30s%s" % (list[1],list[0])

将以上文件保存hy.panic.py

2、相关的死机堆栈信息保存 error.txt

例如:

I/DEBUG   (  634):          #00  pc 000078e6  /system/lib/libmultiplayerservice.so
I/DEBUG   (  634):          #01  pc 000087bc  /system/lib/libmultiplayerservice.so
I/DEBUG   (  634):          #02  pc 0000e94e  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #03  pc 0000a790  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #04  pc 0000d4b2  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #05  pc 0000d852  /system/lib/libsensorservice.so
I/DEBUG   (  634):          #06  pc 00015ece  /system/lib/libutils.so
I/DEBUG   (  634):          #07  pc 0000153a  /system/lib/libsystem_server.so
I/DEBUG   (  634):          #08  pc 00001756  /system/lib/libsystem_server.so
I/DEBUG   (  634):          #09  pc 0000adb8  /system/lib/libandroid_servers.so
I/DEBUG   (  634):          #10  pc 00011cb4  /system/lib/libdvm.so

3、将以上两个文件拷贝到android的编译根路径下面,执行

python hy.panic.py error.txt

方法2使用非常方便,相比于加打印效率大大提高

part three:logcat的基本设置与各种用法小结

在studio中用真机测试的时候由于log太多,很难找到我们需要的log,我们需要对log的数量进行设置,并对log的filter进行设置,方便找到我们需要的log。

本文主要讲4点:

1 先介绍logcat的5大级别

2 设置log的数量

3 设置log各个级别的显示颜色

4怎么设置log才可以方便的找到我们需要的信息 

后3点重要。

1 先介绍logcat的5大级别

info:普通信息

warning:警告

Error:错误,常用

Debug:debug

Assert::断言,没用过

Verbose:冗余,基本没用

2 设置logcat显示的log数量

 找到studio的安装目录 Bin/idea.properties,打开,在 下面添加idea.cycle.buffer.size=1024000  

3 设置log各级别的颜色

file--setting--在搜索中输入  logcat ,选择Android Logcat ,去掉勾选:use inherited attributes,其余的大家看着图设置自己看的顺眼的颜色吧。



4 为了快速找到我们需要的log,一般会在log的输出信息前加“”###“,这样便于查找

见图

filter中设置,这样可以快速找到需要的log

l联机调试:对adb logcat的使用介绍。

当Android运行时,它会收集所有的系统信息。如您所知,程序员、开发者可以选择实时输出状态信息(或是错误信息、调试提示)到系统日志中,Android本身也通过这种方式输出所有有用的信息。

但是,对于一个随时更新的日志,又如何查看它呢?

如果您通过ADB(使用USB或其他方式)连接到设备,试着在计算机上输入adb logcat。Android执行操作日志将实时输出到终端窗口上,可以随时按^C(Ctrl+C)结束。

那么,我们假设您遇到了循环重启的问题,想知道“引擎盖下”到底发生了什么。没问题,您可以查看adb logcat。即使它看上去像流水账一样,您也可以把它的输出(通常错误都比较明显,如果您坐下来看看,可能会找到类似“ERROR!!!!!”的文字)复制粘贴到网上,比如pastebin.com(译注:国内用户访问该网站可能会遇到问题,尝试paste.ubuntu.com)(当然,确保没有将偶现日志中的本地IP或其他敏感个人信息粘贴上去)。您可以以这种方式(通过链接)将该问题展示给其他人,用于以后的讨论、调试等。

无论如何,从现在开始——不要只说“救命!我的机器循环重启!”,而应该说“救命!我的机器循环重启,这是logcat日志链接!”

注意: 

为什么叫“logcat”?以下内容是我的猜测。在Unix(或Linux)下,有一个“cat”(连接文件并输出到标准输出设备(concatenate files and print on the standard output),不管你信不信)命令,用于同时显示多个文件的内容,但通常却被(滥)用作查看单个文件的内容。在此情况下,cat相当于动词。您可以在类Unix操作系统(包括Linux和OS X)终端中输入cat 某个文件.txt,它会显示文件的内容。那么,我猜“logcat”是“显示(cat)log内容”的意思。

红利命令!:如果您使用Linux或OS X,想在终端中查看文件内容,但是不希望像cat filename.txt命令一样没有停顿的显示所有内容,可以使用more filename.txt代替。(它的工作原理留作课后思考。)

原始出处:http://forum.xda-developers.com/showpost.php?p=21353661&postcount=1570

高级用法

过滤

基于优先级

adb logcat提供了额外的功能,可基于日志优先级来过滤日志。用法为adb logcat *:#,其中#为下述选项之一。

距离: 1129  adb logcat *:E 刺客报错会出现比E优先级高的所有的错误,以及相关重点。

 V    详细(表示所有可能的日志,默认级别)
 D    调试(表示所有合理的调试用日志)
 I    信息(表示正常使用时的日志)
 W    警告(表示可能有问题,还没发生错误)
 E    错误(表示有问题并导致出错)
 F    致命(表示有问题导致运行时发生致命错误,通常导致重启)

所有优先级都自动包含比它高的优先级,因此adb logcat *:W包含警告、错误和致命错误。当应用崩溃时,可以使用adb logcat *:E来查看导致该问题的原因,而不必费力去查看那些不着边际的调试用日志。然而在将日志提供给开发者时,应包含所有日志(不要设置任何过滤),因为通过调试日志通常可以找到问题的真正原因。

基于内容

您还可以基于“内容”来过滤。比方说,您要收集所有提到术语“Google”的日志行。可以这么做:

$ adb logcat | grep Google

此命令获取“logcat”的输出(所有东西),并将其“重定向”至grep命令,其搜索“Google”并只返回包含它的行。

小提示

请注意,管道符“|”与大写“I”、小写“L”、数字“1”或其它什么unicode中的竖线图形标志符不同。在美式键盘上,管道符一般可由按住Shift键并按下“\”键打出。管道符可用于将一个命令的输出“重定向”至下个命令的输入中。上述例子中,adb logcat的输出就成为了grep的输入。

如果您想使搜索不区分大小写,只需要添加-i参数:

$ adb logcat | grep -i Google

这会返回带有“Google”、“google”、“gOoGlE”以及其它任意大写小写字符组合的日志行。

颜色

adb logcat -C可用于为日志着色,以增强可读性。

如果您对-C参数不满意,可以使用有额外颜色设置的logcat脚本,或者自己写一个。

  • 由杰夫·夏基(Jeff Sharkey)写的彩色logcat(Git代码库博文
  • 由马歇尔·卡皮普(Marshall Culpepper)写的logcat-color(Git代码库

清空

如果您发现屏幕上塞满了没用的日志信息,但仍需要详细的日志,可以使用adb logcat -c清除日志缓冲区。它会重置日志并只显示重置后的日志内容。

Logcat用于错误跟踪

在设备上使用

这会在你的SD卡上生成一个logcat文件,你可以将它作为附件加入缺陷报告。

  • Open Console Application of your choice (CM <=11.0 comes with 'Terminal Emulator' preinstalled; CM >=12.0 has 'Terminal' that you can turn on in Developer Options)
  • Switch to root (type su and confirm root access) (You may have to turn on root access for apps in Developer Options)
  • Type logcat -d -f /sdcard/logcat.log *:V
  • Alternatively the radio buffer can be viewed with logcat -b radio
-d    makes it dump the logcat
-f    tell it where to save the log to
*:V   gets all Logs in Verbose mode


注意: 

在您复现您要回报的问题“之后”再运行logcat命令。

注意: 

由于谷歌于CM 10.0/Android 4.1(果冻豆,Jellybean)开始更改了Android内部API,设备上的应用程序将需要root权限才能访问完整的logcat(应用程序现在仅限于自己生成的日志)。对于内置的终端模拟器,您只需要在运行logcat命令之前键入su并回车。

参考链接:

https://wiki.cyanogenmod.org/w/Doc:_debugging_with_logcat/zh-cn

http://blog.csdn.net/ss1168805219/article/details/50558310

http://blog.csdn.net/tom_221x/article/details/46789415

http://blog.csdn.net/vichie2008/article/details/43059179

http://blog.csdn.net/helldevil/article/details/6682211

http://bootloader.wikidot.com/linux:android:crashlog

猜你喜欢

转载自blog.csdn.net/darlingqiang/article/details/79253187