精华内容
下载资源
问答
  • 打印调用栈

    千次阅读 2018-06-10 15:09:29
    打印调用栈 我们在实际开发中经常会遇到两种种情况: 1.是谁调用了这个函数,为什么程序会跑到这里来了? 2.我们要分析代码的调用流程。 一.先看java层的 二.c/c++ 层

    打印调用栈

    我们在实际开发中经常会遇到两种种情况:

    • 1.是谁调用了这个函数,为什么程序会跑到这里来了?
    • 2.我们要分析代码的调用流程。

    我们首先应该都会 grep 一下,或者使用 source insight 等工具搜一下调用函数,一般情况下就能解决问题。但是当遇到情况很多调用,情况又十分复杂的使用就要使用我们的必杀技,打印调用栈。

    一.先看java层的

    java层的比较简单 ,只需要使用下面的函数就能打印出来。
    在需要打印的函数中加入

    Log.d("haha",Log.getStackTraceString(new Throwable()));
    

    修改之后在命令行使用logcat

    logcat -s haha
    

    当有运行到这个函数时就能打印出调用的函数调用光系,如下图:
    在这里插入图片描述
    补充:
    异常时打印当前堆栈
    catch中加入 Exception::printStackTrace()就能把调用栈打印出来


    二.c / c++

    android 4.4 平台使用的例子
    加入头文件并在需要打印的函数中使用下面的函数

    #include <utils/CallStack.h>
    android::CallStack stack("haha");
    

    之后同java一样使用

    logcat -s haha
    

    当有运行到这个函数时就能打印出调用栈,如下图:



    三.内核

    直接在要打印调用栈的函数中加入这个函数,当函数执行到这里,就会通过串口(cat /proc/kmsg)看到信息输出。
    dump_stack();

    展开全文
  • android 打印调用栈

    2020-07-28 18:30:25
    java 打印调用栈: Log.d(TAG, Log.getStackTraceString(new Throwable())); c++,比如netd里 Android为方便Native层打印函数的调用堆栈,专门在system/core/libutils下设计了CallStack.cpp类 如果需要打印...

    转载自:https://blog.csdn.net/u010116586/article/details/91486568

     

    java 打印调用栈:

     

    Log.d(TAG, Log.getStackTraceString(new Throwable()));

     

    c++,比如netd里

    Android为方便Native层打印函数的调用堆栈,专门在system/core/libutils下设计了CallStack.cpp类
    如果需要打印Native的stack只需要在自己的代码的mk文件中添加对libutils.so添加依赖,在类文件中include <utils/CallStack.h> 头文件。

    实现方法如下:

    .cpp文件
    #include <utils/CallStack.h>

    CallStack stack("powered by gaojian");
     

    在编译文件添加对libutils.so的依赖,如下:

    Android.mk
    LOCAL_SHARED_LIBRARIES += libutils
     

    该方案的缺点:

    1. 需要修改编译文件,有时候依赖libutils会不成功
    2. 只能在cpp文件中使用,无法在.c文件中使用

    为解决该问题,本人百度、google研究了个遍,各种攻略都以失败告终,自己也相当郁闷,
    难道就没有一个简单通用方法在c/c++文件中打印堆栈吗?
    答案是肯定的

    自己去研究了下CallStack .cpp,突发灵感,只要稍微对CallStack .cpp做修改,即可搞定这个问题!!!!

    上代码:

    修改system/core/libutils/CallStack.cpp代码

    diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
    old mode 100644
    new mode 100755
    index bd6015e..56bcf60
    --- a/libutils/CallStack.cpp
    +++ b/libutils/CallStack.cpp
    @@ -26,6 +26,14 @@
     
     #include <backtrace/Backtrace.h>
     
    +extern "C" {
    +void call_stack_fun(const char* value){
    +    char buf[100];
    +    memset(buf, 0, sizeof(buf));
    +    snprintf(buf, sizeof(buf),"SGJ_%s",value);
    +    android::CallStack mCallStack(buf);
    +}
    +}
     namespace android {
     
     CallStack::CallStack() {

    编译出libutils.so,重命名为libutilscallstack.so(当然也可以不重命名,主要是怕和原so冲突)

    然后在想打印trace的C或者C++方法中通过 dlopendlsym方法去调用该方法,代码如下

    --- a/services/camera/libcameraservice/CameraService.cpp
    +++ b/services/camera/libcameraservice/CameraService.cpp
    @@ -64,6 +64,8 @@
     #include "api2/CameraDeviceClient.h"
     #include "utils/CameraTraces.h"

    //++ begin
    #include <dlfcn.h>
    //++ end
     namespace {
         const char* kPermissionServiceName = "permission";
     }; // namespace anonymous
    @@ -181,6 +183,14 @@ void CameraService::onFirstRef()
     {
         ALOGI("CameraService process starting");
    //++ begin 
        void * prt_stack_lib = dlopen("/system/lib/libutilscallstack.so",RTLD_LAZY);
        ALOGE("SGJ dlopen %s:",dlerror());    //有问题时用这个dlerror看下错误信息
        void(*prt_stack_fun)(const char*) = (void (*)(const char *))dlsym(prt_stack_lib,"call_stack_fun");
        if (prt_stack_fun!=NULL) {
            prt_stack_fun("onFirstRef");
        }
        dlclose(prt_stack_lib);
    //++ end


         BnCameraService::onFirstRef();
     

     

     

    展开全文
  • Android打印调用栈

    2014-06-26 17:23:32
    打印调用栈是android平台问题定位的基本方法,如果需要知道谁在调用某个函数,可以在此函数中添加打印调用栈函数,弄清楚函数之间的调用关系。 1.Java层打印调用栈方法 RuntimeException here = new ...


    打印堆栈是调试的常用方法,一般在系统异常时,我们可以将异常情况下的堆栈打印出来,这样十分方便错误查找。实际上还有另外一个非常有用的功能:分析代码的行为。android代码太过庞大复杂了,完全的静态分析经常是无从下手,因此通过打印堆栈的动态分析也十分必要。

    1. zygote的堆栈dump

    实际上这个可以同时dump java线程及native线程的堆栈,对于java线程,java堆栈和native堆栈都可以得到。

    使用方法很简单,直接在adb shell或串口中输入:

    kill -3 <pid>  

    输出的trace会保存在 /data/anr/traces.txt文件中。这个需要注意,如果没有 /data/anr/这个目录或/data/anr/traces.txt这个文件,需要手工创建一下,并设置好读写权限。

    如果需要在代码中,更容易控制堆栈的输出时机,可以用以下命令获取zygote的core dump:

    Process.sendSignal(pid, Process.SIGNAL_QUIT); 

    原理和命令行是一样的。

    不过需要注意两点:

    1.adb shell可能会没有权限,需要root。

    2.android 4.2中关闭了native thread的堆栈打印,详见 dalvik/vm/Thread.cpp的dumpNativeThread方法:

    code as:

    1. dvmPrintDebugMessage(target,  
    2.     "\"%s\" sysTid=%d nice=%d sched=%d/%d cgrp=%s\n",  
    3.     name, tid, getpriority(PRIO_PROCESS, tid),  
    4.     schedStats.policy, schedStats.priority, schedStats.group);  
    5. dumpSchedStat(target, tid);  
    6. // Temporarily disabled collecting native stacks from non-Dalvik  
    7. // threads because sometimes they misbehave.  
    8. //dvmDumpNativeStack(target, tid);  
    Native堆栈的打印被关掉了!不过对于大多数情况,可以直接将这个注释打开。

    2. debuggerd的堆栈dump

    debuggerd是android的一个daemon进程,负责在进程异常出错时,将进程的运行时信息dump出来供分析。debuggerd生成的coredump数据是以文本形式呈现,被保存在 /data/tombstone/ 目录下(名字取的也很形象,tombstone是墓碑的意思),共可保存10个文件,当超过10个时,会覆盖重写最早生成的文件。从4.2版本开始,debuggerd同时也是一个实用工具:可以在不中断进程执行的情况下打印当前进程的native堆栈。使用方法是:

    debuggerd -b <pid>

    这可以协助我们分析进程执行行为,但最最有用的地方是:它可以非常简单的定位到native进程中锁死或错误逻辑引起的死循环的代码位置。




    3.Java层打印调用栈方法
    RuntimeException here = new RuntimeException("here");
    here.fillInStackTrace();
    Log.w(TAG, "Called: " + this, here);


     

    4. C++层打印调用栈方法

    C++也是支持异常处理的,异常处理库中,已经包含了获取backtrace的接口,Android也是利用这个接口来打印堆栈信息的。在Android的C++中,已经集成了一个工具类CallStack,在libutils.so中,使用方法:

    CallStack stack;
    stack.update();
    stack.dump();

    PS:此方法不适用NDK,或者是本人未找到在NDK下面使用CallStack的方法


    备注:下面操作是可选操作,但加上去之后会有一些额外的功能

    #define HAVE_DLADDR 1 :可以从lib中自己转成c++代码行,不需要手动反编译

    #define HAVE_CXXABI 1:将c++ 已被namemangling的函数名转化为源文件中定义的函数名。

    并在文件frameworks/base/libs/utils/Android.mk中大约105行(LOCAL_SHARED_LIBRARIES)后添加

    ifeq ($(TARGET_OS),linux)

    LOCAL_SHARED_LIBRARIES += libdl

    endif重新编译push生成的libutils.so到/system/lib/目录下,重启设备。

    此外,由于CallStack.dump中使用的LOGD进行的打印,因此需要将后台的LogLevel设置为D一下才能出来。


     

    5. C函数打印调用栈

    [可以参考CallStack.cpp的实现,通过调用_Unwind_Backtrace完成。]

        C代码,尤其是底层C库,想要看到调用的堆栈信息,还是比较麻烦的。 CallStack肯定是不能用,一是因为其实C++写的,需要重新封装才能在C中使用,二是底层库反调上层库的函数,会造成链接器循环依赖而无法链接。不过也不是没有办法,可以通过android工具类CallStack实现中使用的unwind调用及符号解析函数来处理。

    这里需要注意的是,为解决链接问题,最好使用dlopen方式,查找需要用到的接口再直接调用,这样会比较简单。如下为相关的实现代码,只需要在要打印的文件中插入此部分代码,然后调用getCallStack()即可,无需包含太多的头文件和修改Android.mk文件:

    1. #define MAX_DEPTH                       31  
    2. #define MAX_BACKTRACE_LINE_LENGTH   800  
    3. #define PATH "/system/lib/libcorkscrew.so"  
    4.   
    5. typedef ssize_t (*unwindFn)(backtrace_frame_t*, size_tsize_t);  
    6. typedef void (*unwindSymbFn)(const backtrace_frame_t*, size_t, backtrace_symbol_t*);  
    7. typedef void (*unwindSymbFreeFn)(backtrace_symbol_t*, size_t);  
    8.   
    9. static void *gHandle = NULL;  
    10.   
    11. static int getCallStack(void){  
    12.     ssize_t i = 0;  
    13.     ssize_t result = 0;  
    14.     ssize_t count;  
    15.     backtrace_frame_t mStack[MAX_DEPTH];  
    16.     backtrace_symbol_t symbols[MAX_DEPTH];  
    17.   
    18.     unwindFn unwind_backtrace = NULL;  
    19.     unwindSymbFn get_backtrace_symbols = NULL;  
    20.     unwindSymbFreeFn free_backtrace_symbols = NULL;  
    21.   
    22.     // open the so.  
    23.     if(gHandle == NULL) gHandle = dlopen(PATH, RTLD_NOW);  
    24.   
    25.     // get the interface for unwind and symbol analyse  
    26.     if(gHandle != NULL) unwind_backtrace = (unwindFn)dlsym(gHandle, "unwind_backtrace");  
    27.     if(gHandle != NULL) get_backtrace_symbols = (unwindSymbFn)dlsym(gHandle, "get_backtrace_symbols");  
    28.     if(gHandle != NULL) free_backtrace_symbols = (unwindSymbFreeFn)dlsym(gHandle, "free_backtrace_symbols");  
    29.   
    30.     if(!gHandle ||!unwind_backtrace ||!get_backtrace_symbols || !free_backtrace_symbols  ){  
    31.         ALOGE("Error! cannot get unwind info: handle:%p %p %p %p",  
    32.             gHandle, unwind_backtrace, get_backtrace_symbols, free_backtrace_symbols );  
    33.         return result;  
    34.     }  
    35.   
    36.     count= unwind_backtrace(mStack, 1, MAX_DEPTH);  
    37.     get_backtrace_symbols(mStack, count, symbols);  
    38.   
    39.     for (i = 0; i < count; i++) {  
    40.         char line[MAX_BACKTRACE_LINE_LENGTH];  
    41.   
    42.         const char* mapName = symbols[i].map_name ? symbols[i].map_name : "<unknown>";  
    43.         const char* symbolName =symbols[i].demangled_name ? symbols[i].demangled_name : symbols[i].symbol_name;  
    44.         size_t fieldWidth = (MAX_BACKTRACE_LINE_LENGTH - 80) / 2;  
    45.           
    46.         if (symbolName) {  
    47.             uint32_t pc_offset = symbols[i].relative_pc - symbols[i].relative_symbol_addr;  
    48.             if (pc_offset) {  
    49.                 snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d  pc %08x  %.*s (%.*s+%u)",  
    50.                         i, symbols[i].relative_pc, fieldWidth, mapName,  
    51.                         fieldWidth, symbolName, pc_offset);  
    52.             } else {  
    53.                 snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d  pc %08x  %.*s (%.*s)",  
    54.                         i, symbols[i].relative_pc, fieldWidth, mapName,  
    55.                         fieldWidth, symbolName);  
    56.             }  
    57.         } else {  
    58.             snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d  pc %08x  %.*s",  
    59.                     i, symbols[i].relative_pc, fieldWidth, mapName);  
    60.         }  
    61.   
    62.         ALOGD("%s", line);  
    63.     }  
    64.   
    65.     free_backtrace_symbols(symbols, count);  
    66.   
    67.     return result;  
    68. }  

    对sched_policy.c的堆栈调用分析如下,注意具体是否要打印,在哪里打印,还可以通过pid、uid、property等来控制一下,这样就不会被淹死在trace的汪洋大海中。

      PS:该方法可用,但是不是线程安全的(async-signal-safe);无法再signal的处理函数中使用


    6. Kernel层打印调用栈方法
    dump_stack();函数



    展开全文
  • android打印调用栈

    2017-06-14 09:22:47
    Log中打印调用栈 Log.d(TAG,Log.getStackTraceString(new Throwable()));

    Log中打印调用栈

    Log.d(TAG,Log.getStackTraceString(new Throwable()));


    展开全文
  • Android平台打印调用栈

    2015-09-08 20:04:12
    Android平台打印调用栈
  • android打印调用栈的方法 http://blog.sina.com.cn/s/blog_67892f910101f3cb.html 打印调用栈是android平台问题定位的基本方法,如果需要知道谁在调用某个函数,可以在此函数中添加打印调用栈函数,弄清楚函数之间的...
  • Android中打印调用栈

    2014-03-02 09:31:31
    打印调用栈是android平台问题定位的基本方法,如果需要知道谁在调用某个函数,可以在此函数中添加打印调用栈函数,弄清楚函数之间的调用关系。 1. Java层打印调用栈方法 RuntimeException here = new ...
  • Android下打印调用栈

    2014-11-20 11:10:05
    Android下打印调用栈 1. Java层如何打印调用栈? 在优化Android启动过程时,同事给出一种打印出调用栈的函数。分享一下  java.util.Map ts = Thread.getAllStackTraces();   StackTraceElement[] ste = ...
  • android native 调试 打印调用栈

    千次阅读 2019-01-21 15:56:20
    在调试 android 某些应用时,需要打印调用栈, 但是高版本的5.0 以上已经去掉了libcorkscrew.so 和 libcutils.so 两个库, 改用其他的google 库文件,但是可以使用andorid 4.4 , 4.3 系统使用。 使用时可以直接...
  • C++中打印调用栈

    千次阅读 2015-03-30 18:11:03
    在需要打印调用栈的地方加上 dumpCallStack(__FUNCTION__);
  • linux下打印调用栈

    2014-04-11 09:39:13
    #include #include .../* 打印调用栈的最大深度 */ #define DUMP_STACK_DEPTH_MAX 16 /* 打印调用栈函数 */ void dump_trace() { void *stack_trace[DUMP_STACK_DEPTH_MAX] = {0}; cha
  • Android JAVA源码之打印调用栈,Throwable().getStackTrace
  • 一、C++打印调用栈 1.包含两个头文件 #include <utils/Log.h> #include <utils/CallStack.h> 2.编写打印调用栈函数 void dumping_callstack() { CallStack stack; //如果这里的函数不在android命名...
  • Android C++层打印调用栈

    千次阅读 2017-02-06 20:44:12
    在Android framework的C++层或其他C++服务中需要打印调用栈时,可以使用android中的CallStack类进行打印,该类的实现如下: /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the ...
  • android中打印调用栈

    2015-09-09 10:44:36
    Android中打印调用栈 包括C++/java/c http://www.07net01.com/program/549412.html 打印堆栈是调试的常用方法,一般出现异常时,我们可以在跑出异常时也将堆栈情况打印出来,这样十分方便错误查找。另外实际...
  • andorid 打印调用栈

    2019-04-19 15:29:31
    在Android调试过程中经常会出现程序出现的结果不是我们预期的结果,那就需要加Log打印调试,看调用过程是否正确,此时就需要打印程序的调用栈,特别是Android代码相当庞大,打印堆栈更有利于我们分析问题,下面就...
  • 在C/C++程序里打印调用栈信息 我们知道,GDB的backtrace命令可以查看堆栈信息。但很多时候,GDB根本用不上。比如说,在线上环境中可能没有GDB,即使有,也不太可能让我们直接在上面调试。如果能让程序自己输出...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,343
精华内容 537
关键字:

打印调用栈