Android打印堆栈

Android打印堆栈

      • java打印堆栈
          • 方法一:异常对象打印堆栈
          • 方法二:Log打印获取异常的堆栈并打印
      • C++\C打印堆栈
          • 方法一:linux函数
          • 方法二:使用Android工具方法
      • kernel打印堆栈
      • 注意

java打印堆栈

方法一:异常对象打印堆栈
Exception e = new Exception("this is a log");
e.printStackTrace();
方法二:Log打印获取异常的堆栈并打印
Log.e(“dump_test”,Log.getStackTraceString(new Throwable()));

C++\C打印堆栈

方法一:linux函数

函数介绍
头文件:

#include 

函数方法:

// 获取当前的调用栈信息,结果存储在buffer中,返回值为栈的深度,参数size限制栈的最大深度,即最大取size步的栈信息。
int backtrace(void **buffer, int size);
// 把backtrace获取的栈信息转化为字符串,以字符指针数组的形式返回,参数size限定转换的深度,一般用backtrace调用的返回值。
char **backtrace_symbols(void *const *buffer, int size);
// 它的功能和backtrace_symbols差不多,只不过它不把转换结果返回给调用方,而是写入fd指定的文件描述符。
void backtrace_symbols_fd(void *const *buffer, int size, int fd);

编译选项

 -rdynamic 
 -g 

gcc编译时加上-rdynamic和-g编译选项,就可以看到被调用的函数和地址,如下

stackstrace begin:
./test3(_Z16print_stacktracev+0x26) [0x4008e5]
./test3(_Z4fun1v+0x13) [0x4008a7]
./test3(_Z4fun2v+0x9) [0x4008b2]
./test3(_Z4fun3v+0x9) [0x4008bd]
./test3(main+0x9) [0x40088d]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xff) [0x7fa9558c1eff]
./test3() [0x4007c9]

堆栈转换
若有一个函数有多个地方被调用,可以使用addr2line,把调用地址转换为行数

// addr2line -aCfe lib addr
$ addr2line -aCfe 0x4008a7 test3
0x00000000004008a7
fun1()
/home/wuzesheng/work/test/test.cc:20

Android使用编译选项
在Android中,编译脚本是Android源码中已经写好的,可以在Android.mk中以下面方式添加编译选项

LOCAL_CFLAGS += -rdynamic -g

linux下使用编译选项
非Android编译,使用如下命令

gcc test.cc -rdynamic -g -o test3

示例:

#include 
       #include 
       #include 
       #include 

       void
       myfunc3(void)
       {
           int j, nptrs;
       #define SIZE 100
           void *buffer[100];
           char **strings;

           nptrs = backtrace(buffer, SIZE);
           printf("backtrace() returned %d addresses\n", nptrs);

           /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
              would produce similar output to the following: */

           strings = backtrace_symbols(buffer, nptrs);
           if (strings == NULL) {
               perror("backtrace_symbols");
               exit(EXIT_FAILURE);
           }

           for (j = 0; j < nptrs; j++)
               printf("%s\n", strings[j]);

           free(strings);
       }

       static void   /* "static" means don't export the symbol... */
       myfunc2(void)
       {
           myfunc3();
       }

       void
       myfunc(int ncalls)
       {
           if (ncalls > 1)
               myfunc(ncalls - 1);
           else
               myfunc2();
       }

       int
       main(int argc, char *argv[])
       {
           if (argc != 2) {
               fprintf(stderr, "%s num-calls\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           myfunc(atoi(argv[1]));
           exit(EXIT_SUCCESS);
       }
方法二:使用Android工具方法

示例:
C++中

<1>.test.cpp
  #include 
  #include 
  void dumping_callstack(){
   android::CallStack stack;
   //getpid()和gettid()效果一样
   //stack.update(2,getpid());
   //stack.update(2,gettid());
 
  stack.update();
  //输出到printf
  stack.dump(1);
  //输出到logcat
  stack.log("dump_test");
  //可以设置第2、3个参数
  //stack.log("Dumping Stack",ANDROID_LOG_ERROR ,"123 ");
}
 
void func1(){
  dumping_callstack();
}
 
void func2(){
 
  func1();
}
 
void func3(){
 
  func2();
}
int main(){
  ALOGE("main_test------------------>");
 
  func3();
}
 
 <2>.Android.mk
  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
  LOCAL_SRC_FILES := test.cpp
  LOCAL_MODULE_TAGS := optional
  LOCAL_MODULE := test
  LOCAL_SHARED_LIBRARIES += libcutils libutils
  include $(BUILD_EXECUTABLE)

C中

 <1>.创建callstack.cpp
   #include 
   extern "C" void dumping_callstack();
 
   void dumping_callstack(){
      android::CallStack stack;
      stack.update();
      stack.log(“dump_test“);
   }
  <2>.创建callstack.h
      void dumping_callstack();
  <3>.测试test.c
      #include "callstack.h"
 
      static ssize_t out_write(){
        dumping_callstack();
      }
  <4>.Anroid.mk中添加到编译选项:callstack.cpp及库
      LOCAL_SHARED_LIBRARIES := libcutils libutils
      LOCAL_SRC_FILES := callstack.cpp

kernel打印堆栈

#include 
printk(KERN_ERR "dump_stack start: %s() %d \n",__FUNCTION__,__LINE__);  
 
dump_stack();
.......
printk(KERN_ERR "dump_stack stop: %s() %d \n",__FUNCTION__,__LINE__);  
根据dump stack的log位置加printk()。

注意

java经过实践测试。
C++\C部分未经过实际完整测试,其中命令都零散的使用过,若参照使用,请根据实际情况调整,整体思路应该没错。实测部分,后面尽量补上

你可能感兴趣的:(Android系统开发)