【问题标题】:Can I get a C++ stack trace when Android app crashes?当 Android 应用程序崩溃时,我可以获得 C++ 堆栈跟踪吗?
【发布时间】:2012-06-27 00:58:39
【问题描述】:

我的 C++ 代码中发生的大多数错误都会导致应用程序简单地退出,没有任何 LogCat 输出,并且设备上也没有消息。空指针和错误使用 JNI 经常会产生这种结果,而且不用说,它会使调试变得非常困难。

目前我可以在 ndk-gdb 中使用“bt”命令获取堆栈跟踪,但如果崩溃发生在启动的前 2 秒内,则不能,因为 ndk-gdb 启动进程并在它启动后附加到它.另外,ndk-gdb 不可靠,经常说它找不到任何符号,或者抱怨非致命的“SIGILL”错误,例如。

有没有办法在应用崩溃时捕获错误并打印堆栈跟踪或其他信息?例如,如果有一个 SIGSEGV,我想知道应用试图访问哪个地址。

【问题讨论】:

标签: android c++ debugging


【解决方案1】:

trace.txt 文件给点什么?我不记得他的位置是:/data/anr/trace.txt 还是/data/data/{pkg}/trace.txt

【讨论】:

    【解决方案2】:

    您需要首先捕获 SIGSEGV 以在获得 segv 时执行代码。这是posix代码,所以类似的东西应该在android上工作:

    void abortHandler( int signum, siginfo_t* si, void* unused )
    {
       const char* name = NULL;
       switch( signum )
       {
       case SIGABRT: name = "SIGABRT";  break;
       case SIGSEGV: name = "SIGSEGV";  break;
       case SIGBUS:  name = "SIGBUS";   break;
       case SIGILL:  name = "SIGILL";   break;
       case SIGFPE:  name = "SIGFPE";   break;
       case SIGPIPE: name = "SIGPIPE";  break;
       }
    
       if ( name )
          printf( stderr, "Caught signal %d (%s)\n", signum, name );
       else 
          printf( stderr, "Caught signal %d\n", signum );
    
       printStackTrace( stderr );
    
       exit( signum );
    }
    
    void handleCrashes()
    {
       struct sigaction sa;
       sa.sa_flags = SA_SIGINFO;
       sa.sa_sigaction = abortHandler;
       sigemptyset( &sa.sa_mask );
    
       sigaction( SIGABRT, &sa, NULL );
       sigaction( SIGSEGV, &sa, NULL );
       sigaction( SIGBUS,  &sa, NULL );
       sigaction( SIGILL,  &sa, NULL );
       sigaction( SIGFPE,  &sa, NULL );
       sigaction( SIGPIPE, &sa, NULL );
    }
    

    接下来是调用该函数来注册信号处理程序。您可以将其作为 main 中的第一件事,但在 main 之前您不会获得堆栈跟踪。如果你以前想要它们,你可以从全局对象的构造函数中调用这个函数。但是不能保证它会是第一个被调用的构造函数。有一些方法可以确保它被尽早调用。例如,重载 operator new - 在调试版本中 - 首先在第一次分配时初始化堆栈跟踪,然后调用真正的 operator new。这将为您提供从第一次分配开始的堆栈跟踪。

    要打印堆栈跟踪:

    void printStackTrace( unsigned int max_frames = 63 )
    {
       void* addrlist[max_frames+1];
    
       // retrieve current stack addresses
       u32 addrlen = backtrace( addrlist, sizeof( addrlist ) / sizeof( void* ));
    
       if ( addrlen == 0 ) 
       {
          printf( stderr, "  <empty, possibly corrupt>\n" );
          return;
       }
    
       char** symbollist = backtrace_symbols( addrlist, addrlen );
    
       for ( u32 i = 3; i < addrlen; i++ )
          printf( stderr, "%s\n", symbollist[i] ):
    }
    

    您需要做更多的工作来解开符号以使其可读。试试 abi::__cxa_demangle。当然使用 -g 构建并使用 -rdynamic 链接。

    【讨论】:

    • 谢谢。我修复了我正在寻找的错误,但下次我一定会试一试。我不确定我是否理解-rdynamic,尽管我查看了文档:“在支持它的目标上将标志 -export-dynamic 传递给 ELF 链接器。这指示链接器添加所有符号,而不仅仅是使用的符号, 到动态符号表。dlopen 的某些用途需要此选项或允许从程序中获取回溯。 (-g 同时,“打开目标首选格式的调试信息”。)
    • 废话! backtrace 应该在 execinfo.h 中,但它在 Android 上不存在! (execinfo.h: 没有这样的文件或目录)
    • 是的,Android 上没有backtrace
    • 此代码仅适用于 glibc/Linux。在 Bionic/Android 下可以使用自带的 libunwind 实现。
    【解决方案3】:

    是的,'execinfo.h' 不存在,但 CallStack 存在:

    #include <utils/CallStack.h>
    ..
    CallStack cs;
    cs.dump();
    

    希望它可以对此类信号处理程序有所帮​​助。

    【讨论】:

    【解决方案4】:

    按照这些解释:https://developer.android.com/ndk/guides/ndk-stack

    也就是说:

    1. 转到您的 libnative-lib.so(或其他名称)文件所在的文件夹;请务必选择方便的文件夹(即与您的测试设备处理器的架构相对应的文件夹)
    2. 将 logcat 的内容复制/粘贴到 txt 文件中(例如 foo.txt);确保此日志包含您的崩溃 :) 将如下所示:

    --------- 崩溃开始 2021-12-22 11:01:37.533 7268-11335/? A/libc:致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR),tid 11335 (Thread-87) 中的故障地址 0x1,pid 7268 等等......(之后很多行)

    1. 将此 foo.txt 文件放在与您的 libnative-lib.so 文件夹相同的文件夹中
    2. 确保在 /my_user_name/.bash_profile 文件中有 NDK 的路径;类似:

    导出 ANDROID_NDK=/Users/my_user_name/Library/Android/sdk/ndk/22.1.7171670

    1. 返回包含您的架构文件夹的文件夹(对我来说,是:/app/build/intermediates/cxx/RelWithDebInfo/5ww1v5k5/obj)并输入终端:

      $ANDROID_NDK/ndk-stack -sym arm64-v8a -dump arm64-v8a/foo.txt

    将在终端中生成人类可读的堆栈跟踪。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 2019-07-26
      • 1970-01-01
      相关资源
      最近更新 更多