文档章节

Android下面打印进程函数调用堆栈(dump backtrace)的方法

shzwork
 shzwork
发布于 08/01 16:12
字数 923
阅读 1
收藏 0

1.         为什么要打印函数调用堆栈?

打印调用堆栈可以直接把问题发生时的函数调用关系打出来,非常有利于理解函数调用关系。比如函数A可能被B/C/D调用,如果只看代码,B/C/D谁调用A都有可能,如果打印出调用堆栈,直接就把谁调的打出来了。

不仅如此,打印函数调用堆栈还有另一个好处。在Android代码里,函数命名很多雷同的,虚函数调用,几个类里的函数名相同等,即使用source insight工具看也未必容易看清函数调用关系。如果用了堆栈打印,很容易看到函数调用逻辑。

那么一个问题来了,Android/kernel本身在发生问题(kernel panic, tombstone, …)时,都可以打出详细的堆栈信息,这里干嘛还要费劲研究打堆栈?答案是发生问题时的堆栈的确很详细,但这里研究的是不影响(准确说是基本不影响)系统运行的境况下,打印出某个情形下的堆栈信息,这个对源代码逻辑研究很有帮助。

 

2.         Linux Kernel

Kernel里最简单,直接有几现成的函数可以使用:

dump_stack() 这个函数打出当前堆栈和函数调用backtrace后接着运行

WARN_ON(x) 这个函数跟dump_stack很像,它有个条件,如果条件满足了就把stack打出来。

打印出来的结果都在kernel log里,一般dmesg命令就可以看到了

 

3.         Native C++

Android在新版(至少5.0, 6.0)里加入了CallStack类,这个类可以打出当前的backtrace。用法很简单:

Ø  前面确保包含头文件#include 《utils/CallStack.h》//这个博客模板不支持头文件的尖括号

Ø  Android.mk的库依赖列表(LOCAL_SHARED_LIBRARIES)里包含libutils,一般都已经包含了。

Ø  然后在要打印堆栈处加入android::CallStack cs(“haha”);

“haha”是在logcat输出的TAG,这里可以自己定义。如果上下文已经在android namespace里,”android::”前缀就不必加了。

Native C++的输出log可以在logcat里看到。

 

注意,在网上的一些文档里说要这么用:

CallStack stack; 

stack.update(); 

stack.dump();

这样做已经不行了,在新版Android里编译不过。

 

4.         Native C

Android对C的堆栈打印支持不太好。过去网上的文章一般是推荐libcorkscrew.so,并加入大段代码来unwind_backtrace。新版Android上libcorkscrew已经被拿掉了,网上的加载libcorkscrew库的方法自然就不能用了。

 

一个简单方法是用C语言调C++的函数,对,就是extern “C”。

先在项目里加入一个c++文件,比如callstack.cpp,里面是:

#include 《utils/CallStack.h》

extern "C" void dumping_callstack(void);

void dumping_callstack(void)

{

         android::CallStack cs("Jamie");

}

在项目里再加入一个c++的头文件,比如callstack.h,里面是:

void dumping_callstack(void);

 

在Android.mk里源文件列表LOCAL_SRC_FILES里加入callstack.cpp,确保libutils在依赖列表里。

在native C里include callstack.h后直接调用dumping_callstack()就可以了。

这个log也可以在logcat里看到。

 

5.         Java

Java最简单,它的backtrace最详细,连文件名和行号都打出来了:

Exception e = new Exception("haha");

e.printStackTrace();

log在logcat里看以看到。

本文转载自:http://blog.sina.com.cn/s/blog_7213e0310102wtge.html

shzwork
粉丝 15
博文 817
码字总数 10675
作品 0
厦门
私信 提问
(转)Android平台的崩溃捕获机制及实现

作者简介:贾志凯,Testin崩溃分析(http://apm.testin.cn/)项目研发工程师,负责客户端SDK相关技术研发工作。5年移动互联网开发经验,曾任职于中科院、Symantec、Opera,对移动App的测试、分...

so1per
2016/01/18
4.1K
0
如何定位Android NDK开发中遇到的错误

正式开始这个话题之前,先简单介绍一下什么是NDK和JNI,部分内容来自网络 Android NDK是什么,为什么我们要用NDK? Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Ki...

糊涂熊
2014/12/16
15K
2
如何定位Android NDK开发中遇到的错误

正式开始这个话题之前,先简单介绍一下什么是NDK和JNI,部分内容来自网络 Android NDK是什么,为什么我们要用NDK? Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Ki...

糊涂熊
2014/12/16
16
0
Android开发:调试工具集

查看当前堆栈 1) 功能:在程序中加入代码,使可以在logcat中看到打印出的当前函数调用关系 2) 方法: new Exception(“print trace”).printStackTrace(); 2. MethodTracing 1) 功能:用于热...

carlos
2014/10/13
134
1
android debug工具集

1.TraceView 1)功能:用于热点分析和性能优化,分析每个函数占用的CPU时间,调用次数,函数调用关系等  2)方法:   a)在程序代码中加入追踪开关   import android.os.Debug;   …… ...

垂盆草
2012/08/18
313
0

没有更多内容

加载失败,请刷新页面

加载更多

JS其他类型值转化为Boolean类型规则

本文转载于:专业的前端网站➤JS其他类型值转化为Boolean类型规则 由于最近在笔试的时候,发现好多关于其他类型转化为Boolean类型的题目,因此总结一下! 一、String类型转化为Boolean 1.转化...

前端老手
35分钟前
4
0
EurekaClient自动装配及启动流程解析

在上篇文章中,我们简单介绍了EurekaServer自动装配及启动流程解析,本篇文章则继续研究EurekaClient的相关代码 老规矩,先看spring.factories文件,其中引入了一个配置类EurekaDiscoveryClie...

Java学习录
41分钟前
6
0
析构函数是否必须为虚函数?为何?

p517 在C++中,基类指针可以指向一个派生类的对象。如果基类的析构函数不是虚函数,当需要delete这个指向派生类的基类指针时,就只会调用基类的析构函数,而派生类的析构函数无法被调用。容易...

天王盖地虎626
41分钟前
5
0
【TencentOS tiny】深度源码分析(7)——事件

引言 大家在裸机编程中很可能经常用到flag这种变量,用来标志一下某个事件的发生,然后在循环中判断这些标志是否发生,如果是等待多个事件的话,还可能会if((xxx_flag)&&(xxx_flag))这样子做...

杰杰1号
45分钟前
8
0
聊聊nacos client的ServerHttpAgent

序 本文主要研究一下nacos client的ServerHttpAgent HttpAgent nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/http/HttpAgent.java public interface HttpAgent { ......

go4it
51分钟前
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部