遇到如下的崩溃
03-07 16:15:31.993 7501-7501/com.netease.nrtc.demo A/libc: invalid address or address of corrupt block 0xb87bccd0 passed to dlfree
03-07 16:15:31.994 7501-7501/com.netease.nrtc.demo A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 7501 (tease.nrtc.demo)
03-07 16:15:32.172 3746-3746/? A/DEBUG: pid: 7501, tid: 7501, name: tease.nrtc.demo >>> com.netease.nrtc.demo <<<
03-07 16:15:32.245 3746-3746/? A/DEBUG: #01 pc 000d031b /data/app/com.netease.nrtc.demo-1/lib/arm/libnrtc_engine.so
03-07 16:15:32.245 3746-3746/? A/DEBUG: #02 pc 000d03bb /data/app/com.netease.nrtc.demo-1/lib/arm/libnrtc_engine.so
03-07 16:15:32.245 3746-3746/? A/DEBUG: #03 pc 000d0415 /data/app/com.netease.nrtc.demo-1/lib/arm/libnrtc_engine.so
03-07 16:15:32.245 3746-3746/? A/DEBUG: #04 pc 008f6017 /data/app/com.netease.nrtc.demo-1/oat/arm/base.odex (offset 0x4d1000) (void com.netease.nrtc.rec.impl.RecEngine.dispose(long)+82)
03-07 16:15:32.245 3746-3746/? A/DEBUG: #05 pc 008f43bb /data/app/com.netease.nrtc.demo-1/oat/arm/base.odex (offset 0x4d1000) (void com.netease.nrtc.rec.impl.RecEngine.a()+462)
03-07 16:15:32.246 3746-3746/? A/DEBUG: #06 pc 008eaef9 /data/app/com.netease.nrtc.demo-1/oat/arm/base.odex (offset 0x4d1000) (void com.netease.nrtc.engine.a.c.leaveChannel()+964)
03-07 16:15:32.246 3746-3746/? A/DEBUG: #07 pc 008c398f /data/app/com.netease.nrtc.demo-1/oat/arm/base.odex (offset 0x4d1000) (int com.netease.nrtc.b.leaveChannel()+178)
03-07 16:15:32.246 3746-3746/? A/DEBUG: #08 pc 009acbf9 /data/app/com.netease.nrtc.demo-1/oat/arm/base.odex (offset 0x4d1000) (void com.netease.nrtc.demo.ChatActivity.leave()+60)
03-07 16:15:32.246 3746-3746/? A/DEBUG: #09 pc 009afa47 /data/app/com.netease.nrtc.demo-1/oat/arm/base.odex (offset 0x4d1000) (void com.netease.nrtc.demo.ChatActivity.onBackPressed()+90)
1.可知崩溃发生在000d031b
这个地址处。使用addr2line
工具将一个地址转为一个符号。
$ addr2line -e libnrtc_engine.so -f 000d031b
_ZTv0_n12_NSt6__ndk118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev
??:?
2.使用c++filt
工具将这个符号转为一个可读的形式!因为C++编译器为了支持函数的重载有一系列的规则用于生成唯一的函数名。具体不同的编译器生成的规则各不相同。命令如下:
$ c++filt _ZTv0_n12_NSt6__ndk118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev
virtual thunk to std::__ndk1::basic_stringstream<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::~basic_stringstream()
3.通过上面的分析,我们得知当前程序是在std::stringstream类的析构方法中执行。
4.一般而言,针对不同CPU架构的so库,我们需要使用对应的工具。Android NDK就提供了这些工具,如arm-linux-androideabi-addr2line,这些工具在NDK路径下的toolchains目录下都可以找到。如果不使用特定版本的工具,可能会无法正常正确解析。