问题
- 您的用户给你反馈了一个Android崩溃日志文件。
- 由于文件仅给出内存地址所以您不知道函数的调用栈。
原因
当您使用发布模式编译项目是,函数符号是不会跟随APK打包的。如果您的应用奔溃了,那么函数调用栈仅会显示内存的地址。
解决方案
对于Unity5.3.5p2和5.4.0,Android的函数符号是存储在您的Unity安装文件夹下面的。
您可以在这里找到Android函数符号:
- MacOS:
/Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Symbols
- Windows:
C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Symbols\armeabi-v7a\libunity.sym.so
您可以使用addr2line工具和符号文件来把内存地址映射成函数名字并创建一个函数调用栈。
例如,假设您的奔溃日志是这样的:
05-26 18:06:51.311: A/libc(26986): Fatal signal 11 (SIGSEGV) at 0x000004e4 (code=1), thread 27024 (Worker Thread)
05-26 18:06:51.411: I/DEBUG(242): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
05-26 18:06:51.411: I/DEBUG(242): Build fingerprint: 'Xiaomi/cancro_wc_lte/cancro:4.4.4/KTU84P/V6.7.1.0.KXDCNCH:user/release-keys'
05-26 18:06:51.411: I/DEBUG(242): Revision: '0'
05-26 18:06:51.411: I/DEBUG(242): pid: 26986, tid: 27024, name: Worker Thread >>> com.u.demo <<<
05-26 18:06:51.411: I/DEBUG(242): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 000004e4
I/DEBUG(242): backtrace:
I/DEBUG(242): #00 pc 006d4960 /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #01 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #02 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #03 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #04 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #05 pc 001c5510 /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #06 pc 001c595c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #07 pc 001c4ec0 /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #08 pc 0043a05c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #09 pc 0000d248 /system/lib/libc.so (__thread_entry+72)
I/DEBUG(242): #10 pc 0000d3e0 /system/lib/libc.so (pthread_create+240)
05-26 18:06:51.311: A/libc(26986): Fatal signal 11 (SIGSEGV) at 0x000004e4 (code=1), thread 27024 (Worker Thread)
05-26 18:06:51.411: I/DEBUG(242): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
05-26 18:06:51.411: I/DEBUG(242): Build fingerprint: 'Xiaomi/cancro_wc_lte/cancro:4.4.4/KTU84P/V6.7.1.0.KXDCNCH:user/release-keys'
05-26 18:06:51.411: I/DEBUG(242): Revision: '0'
05-26 18:06:51.411: I/DEBUG(242): pid: 26986, tid: 27024, name: Worker Thread >>> com.u.demo <<<
05-26 18:06:51.411: I/DEBUG(242): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 000004e4
I/DEBUG(242): backtrace:
I/DEBUG(242): #00 pc 006d4960 /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #01 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #02 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #03 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #04 pc 006d4c0c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #05 pc 001c5510 /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #06 pc 001c595c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #07 pc 001c4ec0 /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #08 pc 0043a05c /data/app-lib/com.u.demo-1/libunity.so
I/DEBUG(242): #09 pc 0000d248 /system/lib/libc.so (__thread_entry+72)
I/DEBUG(242): #10 pc 0000d3e0 /system/lib/libc.so (pthread_create+240)
在上面的调用栈中,加粗的数字(如006d4960)代表执行时发生奔溃的函数的内存地址,而在行尾的是该函数所使用的库(这个实例用的是libunity.so)。
您可以通过对每个内存地址执行addr2line工具来获取对应的函数符号:
> ./arm-linux-androideabi-addr2line -f -C -e /Applications/Unity.app/Content/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Symbols/armeabi-v7a/libunity.sym.so 0043a05c
- -f - 显示函数名字
- -C – 还原后的函数名
- -e – 设置输入文件的名字
为每个地址执行这些命令后,您就可以得到应用奔溃时的函数调用栈:
I/DEBUG(242): backtrace:
I/DEBUG(242): #00 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #01 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #02 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #03 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #04 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #05 JobQueue::ExecuteJobFunc(JobInfo*)
I/DEBUG(242): #06 JobQueue::ExecuteJobFromHighPriorityStack()
I/DEBUG(242): #07 JobQueue::WorkLoop(void*)
I/DEBUG(242): #08 Thread::RunThreadWrapper(void*) 18:06:51.501: I/DEBUG(242): #09 pc 0000d248 /system/lib/libc.so (__thread_entry+72)
I/DEBUG(242): #10 pc 0000d3e0 /system/lib/libc.so (pthread_create+240)
I/DEBUG(242): backtrace:
I/DEBUG(242): #00 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #01 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #02 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #03 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #04 AnimationPlayable::PrepareAnimationEvents(float, dynamic_array<AnimationClipEventInfo, 4u>&)
I/DEBUG(242): #05 JobQueue::ExecuteJobFunc(JobInfo*)
I/DEBUG(242): #06 JobQueue::ExecuteJobFromHighPriorityStack()
I/DEBUG(242): #07 JobQueue::WorkLoop(void*)
I/DEBUG(242): #08 Thread::RunThreadWrapper(void*) 18:06:51.501: I/DEBUG(242): #09 pc 0000d248 /system/lib/libc.so (__thread_entry+72)
I/DEBUG(242): #10 pc 0000d3e0 /system/lib/libc.so (pthread_create+240)
这样,我们就可以正确地阅读函数调用栈并且检测到由动画事件而引发的崩溃。这些信息可为以下的目的服务:
- 创建一个错误报告。
- 复查发布的补丁以寻找一个可能的修复方案。
- 为某些可能发生的问题复查代码。
您可以在Android NDK中找到addr2line工具,地址为:
/android-ndk_auto-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line
请注意:编辑器版本号要与你编译APK时的版本号相同,否则会得到错误的结果。
更多信息
可在以下文档中查到更多有用的信息:
- Unity patch releases homepage