为什么要打印函数调用堆栈?
打印调用堆栈可以直接把问题发生时的函数调用关系打出来,非常有利于理解函数调用关系。比如函数A都有可能,如果打印出调用堆栈,直接就把谁调的打出来了。
不仅如此,打印函数调用堆栈还有另一个好处。在Android工具看也未必容易看清函数调用关系。如果用了堆栈打印,很容易看到函数调用逻辑。
那么一个问题来了,Android/kernel系统运行的境况下,打印出某个情形下的堆栈信息,这个对源代码逻辑研究很有帮助。
Linux Kernel
Kernel里最简单,直接有几现成的函数可以使用:
dump_stack() 这个函数打出当前堆栈和函数调用backtrace后接着运行
WARN_ON(x) 这个函数跟dump_stack打出来。
打印出来的结果都在kernel log命令就可以看到了
Native C++
Android。用法很简单:
前面确保包含头文件#include
Android.mk,一般都已经包含了。
然后在要打印堆栈处加入android::CallStack cs(“haha”);
“haha”前缀就不必加了。
Native C++里看到。
注意,在网上的一些文档里说要这么用:
CallStack stack;
stack.update();
stack.dump();
这样做已经不行了,在新版Android里编译不过。
Native C
Android库的方法自然就不能用了。
一个简单方法是用C。
先在项目里加入一个c++,里面是:
#include
extern "C" void dumping_callstack(void);
void dumping_callstack(void)
{
android::CallStack cs("Jamie");
}
在项目里再加入一个c++,里面是:
void dumping_callstack(void);
在Android.mk在依赖列表里。
在native C就可以了。
这个log里看到。
Java
Java最详细,连文件名和行号都打出来了:
Exception e = new Exception("haha");
e.printStackTrace();
log里看以看到。