首页 > 解决方案 > 解读app c++​​崩溃信息?

问题描述

我特意写了一个触发空指针崩溃的代码,<br />得到了这个崩溃日志:

libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 27802 (sodino.demo), pid 27802 (sodino.demo)
DEBUG   : ABI: 'arm64'
DEBUG   : Timestamp: 2021-07-17 11:23:28+0800
DEBUG   : pid: 27802, tid: 27802, name: sodino.demo  >>> sodino.demo <<<
DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
DEBUG   : Cause: null pointer dereference
DEBUG   :     x0  0000000000000018  x1  000000707e2e4998  x2  0000000000000019  x3  2073796173207070
DEBUG   :     x4  000000707e2e499e  x5  0000007077a70c58  x6  0000000062626161  x7  0000000063636262
DEBUG   :     x8  0000000000000000  x9  0000000000000000  x10 0000000000000000  x11 0000000000000018
DEBUG   :     x12 6820737961732070  x13 206f74206f6c6c65  x14 0000000000000010  x15 000000711109f39a
DEBUG   :     x16 00000071110a4b58  x17 00000071110082bc  x18 0000007115812000  x19 000000708ee10800
DEBUG   :     x20 0000000000000000  x21 000000708ee10800  x22 0000007fcf67f890  x23 0000007114845658
DEBUG   :     x24 0000000000000004  x25 000000711499c020  x26 000000708ee108b0  x27 0000000000000001
DEBUG   :     x28 0000007fcf67f620  x29 0000007fcf67f5c0
DEBUG   :     sp  0000007fcf67f560  lr  000000707e2cc9b8  pc  000000707e2cc9c8
DEBUG   : 
DEBUG   : backtrace:
DEBUG   :       #00 pc 000000000000c9c8  /data/app/sodino.demo-K1-uQOGzzG20SxiRS9-g1Q==/base.apk!libnative-lib.so (offset 0x1000) (concatenateMyStringWithCppString(char const*)+248) (BuildId: fdb041aba6818c49543f4b4e93c433f6d787c772)
DEBUG   :       #01 pc 000000000000c878  /data/app/sodino.demo-K1-uQOGzzG20SxiRS9-g1Q==/base.apk!libnative-lib.so (offset 0x1000) (Java_sodino_demo_MainActivity_stringFromJNI+32) (BuildId: fdb041aba6818c49543f4b4e93c433f6d787c772)

日志中间的内容:

什么是 x0~ x29?什么是sp lr pc


第二个问题:

#00 pc 000000000000c9c8  
/data/app/sodino.demo-K1-uQOGzzG20SxiRS9-g1Q==/base.apk!
libnative-lib.so (offset 0x1000) 
(concatenateMyStringWithCppString(char const*)+248) 
(BuildId: fdb041aba6818c49543f4b4e93c433f6d787c772)

(concatenateMyStringWithCppString(char const*)+248)
什么意思+248

我以为+248是代码行号,
但代码不匹配如下:line 11触发空点崩溃:

核心.h

#ifndef __HelloCpp__Core__
#define __HelloCpp__Core__

#include <iostream>

const char *concatenateMyStringWithCppString(const char *myString);

#endif /* defined(__HelloCpp__Core__) */

核心.cpp

#include <string.h>
#include "Core.h"

const char *CPP_BASE_STRING = "cpp says hello to %s";

const char *concatenateMyStringWithCppString(const char *myString) {
    char *concatenatedString = new char[strlen(CPP_BASE_STRING) + strlen(myString)];
    sprintf(concatenatedString, CPP_BASE_STRING, myString);

    char* p = NULL;
    *p = 0;                    // line 11 crash.
    return concatenatedString;
}

本机 lib.cpp

#include <jni.h>
#include <string>
#include "Core.h"

extern "C" JNIEXPORT jstring JNICALL
Java_sodino_demo_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    const char* result = concatenateMyStringWithCppString("aabbcc");
//    std::string hello = "Hello from C++";
return env->NewStringUTF(result);
}

标签: androidc++armcpu-registersarm64

解决方案


x0 ~ x29 是什么?什么是sp lr pc?

x0 到 x29 是ARM64 的通用寄存器sp,lr并且pcARM 链接和帧指针中所述。

  • sp用于函数中本地数据的堆栈指针。
  • lr调用当前例程的函数/方法的返回地址。
  • pc当前指令。

寄存器是所有商业 CPU 通用的。可以制作仅基于堆栈的架构,但它们通常不能很好地执行。编译器可以识别值并在构建时将它们分配给寄存器。堆栈通常比寄存器慢 5-100 倍。


(concatenateMyStringWithCppString(char const*)+248) 
(BuildId: fdb041aba6818c49543f4b4e93c433f6d787c772)

+248 是什么意思?

这不在代码级别。它是自例程开始以来的指令数concatenateMyStringWithCppString。事实上,如果跟踪代码不能看到所有例程,则指令可能位于不同的函数中。

正常的过程是得到一个汇编列表,之后是(248/4 -> 62)指令。没有看到汇编程序,

const char *concatenateMyStringWithCppString(const char *myString) {
    char *concatenatedString = new char[strlen(CPP_BASE_STRING) + strlen(myString)];
    sprintf(concatenatedString, CPP_BASE_STRING, myString);

    char* p = NULL;
    *p = 0;                    // line 11 crash.
    return concatenatedString;
}

看起来第 11 行将包含大约 62 条指令到例程中,特别是如果strlen()是内联的。编译器选项、版本等将在生成不同代码时更改偏移量与行号。


推荐阅读