public class MainActivity extends AppCompatActivity {
// Used to load the 'ndkcrashdemo' library on application startup.
static {
System.loadLibrary("ndkcrashdemo");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText(stringFromJNI());
}
/**
* A native method that is implemented by the 'ndkcrashdemo' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
故意空指针
#include
#include
extern "C" JNIEXPORT jstring JNICALL
Java_com_cy_ndkcrashdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello=NULL;//故意空指针
hello.c_str();
return env->NewStringUTF(hello.c_str());
}
运行到真机,发生crash,部分LOG如图:
发现并不能看出代码哪里有毛病
工欲善其事必先利其器
addr2lineaddr2line translates addresses into file names and line numbers.
Given an address in an executable or an offset in a section of a relocatable object,
it uses the debugging information to figure out which file name and line number are associated with it.
addr2line
工具是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具。
一般适用于 debug
版本或带有 symbol
信息的库。
addr2line工具在NDK 里的路径如下(注意:每个版本都不一样)
Windows:
32位:D:\AndroidSDK\ndk\21.4.7075529\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\
arm-linux-androideabi-addr2line.exe
64位:D:\AndroidSDK\ndk\21.4.7075529\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\
aarch64-linux-android-addr2line.exe
addr2line命令如下:
The options are:
@<file> Read options from <file>
-a --addresses Show addresses//显示地址
-b --target=<bfdname> Set the binary file format
-e --exe=<executable> Set the input file name (default is a.out)//设置so库的路径
-i --inlines Unwind inlined functions
-j --section=<name> Read section-relative offsets instead of addresses
-p --pretty-print Make the output easier to read for humans//设置输出信息可读性更强
-s --basenames Strip directory names
-f --functions Show function names//显示函数名称
-C --demangle[=style] Demangle function names
-h --help Display this information
-v --version Display the program's version
分析crash log
com.cy.ndkcrashdemo A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 22618 (cy.ndkcrashdemo), pid 22618 (cy.ndkcrashdemo)
DEBUG: Softversion: PD2073B_A_1.8.15
DEBUG: Time: 2022-04-20 15:34:49
DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
DEBUG: Build fingerprint: 'vivo/PD2073/PD2073:11/RP1A.200720.012/compiler1228233519:user/release-keys'
DEBUG: Revision: '0'
DEBUG: ABI: 'arm64'
DEBUG: Timestamp: 2022-04-20 15:34:49+0800
DEBUG: pid: 22618, tid: 22618, name: cy.ndkcrashdemo >>> com.cy.ndkcrashdemo <<<
DEBUG: uid: 10252
DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
DEBUG: Cause: null pointer dereference
DEBUG: x0 0000000000000000 x1 0000000000000000 x2 0000000000000018 x3 00000076eecbf000
DEBUG: x4 0000000000000000 x5 b4000076ee95ac00 x6 00000076497d53af x7 000000000000001b
DEBUG: x8 0**************1 x9 ad1a1eb4209bd757 x10 0000000000430000 x11 00000000069d2cd0
DEBUG: x12 0000000000371314 x13 00000000006476c0 x14 000000000051d6c0 x15 ffffffffffffffff
DEBUG: x16 000000765387ce98 x17 00000076ec1cf4b0 x18 00000076eeec6000 x19 b4000076ee95ac00
DEBUG: x20 0000000000000000 x21 b4000076ee95ac00 x22 00000076eecbf000 x23 b4000076ee95acb8
DEBUG: x24 0000007667d48478 x25 00000076eecbf000 x26 000000000000000b x27 0000000000000002
DEBUG: x28 0000007fdeb3db00 x29 0000007fdeb3da10
DEBUG: lr 000000765385757c sp 0000007fdeb3da00 pc 00000076ec1cf4c0 pst 0000000080001000
DEBUG: backtrace:
DEBUG: #00 pc 00000000000894c0 /apex/com.android.runtime/lib64/bionic/libc.so (strlen_default+16) (BuildId: d010ec9d0da07ff241689a4e9691c733)
DEBUG: #01 pc 000000000000f578 /data/app/~~ipBdrIwT8qi72hDEkPx-ZQ==/com.cy.ndkcrashdemo-bwJhACJJBkJfPLjIt-tS0Q==/lib/arm64/libndkcrashdemo.so (std::__ndk1::char_traits<char>::length(char const*)+20) (BuildId: 34e2ac7e22782a65c51f760e5d9b4376d0cbea1d)
DEBUG: #02 pc 000000000000f064 /data/app/~~ipBdrIwT8qi72hDEkPx-ZQ==/com.cy.ndkcrashdemo-bwJhACJJBkJfPLjIt-tS0Q==/lib/arm64/libndkcrashdemo.so (std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::basic_string<std::nullptr_t>(char const*)+48) (BuildId: 34e2ac7e22782a65c51f760e5d9b4376d0cbea1d)
DEBUG: #03 pc 000000000000efa4 /data/app/~~ipBdrIwT8qi72hDEkPx-ZQ==/com.cy.ndkcrashdemo-bwJhACJJBkJfPLjIt-tS0Q==/lib/arm64/libndkcrashdemo.so (Java_com_cy_ndkcrashdemo_MainActivity_stringFromJNI+56) (BuildId: 34e2ac7e22782a65c51f760e5d9b4376d0cbea1d)
DEBUG: #04 pc 000000000013ced4 /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148) (BuildId: 5aeb6fe6030b3ee85ca5c14f3f2f06e9)
DEBUG: #05 pc 0000000000133564 /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 5aeb6fe6030b3ee85ca5c14f3f2f06e9)
DEBUG: #06 pc 0000000000197e94 /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+204) (BuildId: 5aeb6fe6030b3ee85ca5c14f3f2f06e9)
DEBUG: #07 pc 000000000030347c /apex/com.android.art/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+376) (BuildId: 5aeb6fe6030b3ee85ca5c14f3f2f06e9)
DEBUG: #84 pc 0000000000529d10 /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+92) (BuildId: 5aeb6fe6030b3ee85ca5c14f3f2f06e9)
DEBUG: #85 pc 000000000041bd84 /apex/com.android.art/lib64/libart.so (art::JNI<true>::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+656) (BuildId: 5aeb6fe6030b3ee85ca5c14f3f2f06e9)
DEBUG: #86 pc 0000000000099434 /system/lib64/libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+124) (BuildId: c8f8eb3a06894fb8e5258f8c2f08e801)
DEBUG: #87 pc 00000000000a0ca0 /system/lib64/libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+836) (BuildId: c8f8eb3a06894fb8e5258f8c2f08e801)
DEBUG: #88 pc 0000000000003564 /system/bin/app_process64 (main+1308) (BuildId: a4535eefb34c582385a2cf7c5548aea0)
DEBUG: #89 pc 0000000000088188 /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108) (BuildId: d010ec9d0da07ff241689a4e9691c733)
Cause: null pointer dereference
告诉我们出现了空指针
backtrace
以下,显示了程序调用过程
可以看到自己写的JNI
方法Java_com_cy_ndkcrashdemo_MainActivity_stringFromJNI
+56,这个函数对应的pc
值(函数编译地址)是000000000000efa4
根据 .so 是 32 位还是 64 位选择对应的 addr2line 工具
使用方式如下:
addr2line -f -p -e so文件路径 报错函数对应的pc值
打开命令行窗口,进入aarch64-linux-android-addr2line
(这里举例用的64位)所在目录,输入如下命令:
D:\AndroidSDK\ndk\21.4.7075529\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin>
aarch64-linux-android-addr2line -f -p -e
E:\AndroidStudioWorkspace\NDKCrashDemo\app\build\intermediates\merged_native_libs\
debug\out\lib\arm64-v8a\libndkcrashdemo.so 000000000000efa4
输出如下:
Java_com_cy_ndkcrashdemo_MainActivity_stringFromJNI at
E:/AndroidStudioWorkspace/NDKCrashDemo/app/src/main/cpp/native-lib.cpp:8
指出了crash
发生在哪个文件的哪个函数,以及行号
你也可以将addr2line
工具所在目录添加到系统环境变量path
中,在命令行窗口中不用再进入addr2line
所在目录,也可执行
一个完整的 so 由C/C++代码编译后的输出和
debug
信息组成,这些debug信息会记录 so
中所有方法的对照表,就是方法名和其编译地址的对应表,也叫做符号表,这种so
也叫做未strip
的,通常体积会比较大。通常
release
的 so 都是需要经过一个strip
*** 作的,这样strip之后的 so 中的debug
信息会被剥离,整个 so
的体积也会缩小。
如下可以看到strip之前和之后的大小对比
未strip
的so
已strip
的so
如果debug信息丢了,无法再定位代码。
所以,这些debug信息尤为重要,是我们分析native crash问题的关键信息,那么我们在编译 so
时候务必保留一份未被strip的so 或者剥离后的符号表信息,以供后面问题分析,并且每次编译的so
都需要保存,一旦产生代码修改重新编译,那么修改前后的符号表信息会无法对应,也无法进行分析。
如下图所示,merged_native_libs下是含有debug信息的so,striped_native_libs下是去除了debug信息的so。
注意:不同版本死丢丢目录不一致。
所以开发so
库的时候,每次编译
之后,如果需要提供给别人使用,我们需要保留一份未strip
的so库和JNI代码
,strip
的so库提供给别人使用,当出现native crash
的时候,我们可以通过未strip
的so库定位strip
的so库发生crash的代码位置,因为未strip
和已strip
的so库的函数的编译地址是一致的,strip去除的只是debug
信息。
Github:https://github.com/AnJiaoDe
CSDN:https://blog.csdn.net/confusing_awakening
OpenCV入门教程:https://blog.csdn.net/confusing_awakening/article/details/113372425
ffmpeg入门教程:https://blog.csdn.net/confusing_awakening/article/details/102007792
微信公众号
QQ群
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)