Android打印堆栈
16lz
2021-01-24
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 test30x00000000004008a7fun1()/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横向滚动屏幕特效分析
- 【边做项目边学Android】小白会遇到的问题--创建Android项目不自
- Android(安卓)SharedPreferences总结及优化
- android之listview使用方法(一)
- Android四大组件的工作过程
- Android监听通话正确操作方法介绍
- 从头到尾给你讲明白Android(安卓)View实现原理
- android充当server服务器
- android 应用内悬浮框,并在指定页面显示