守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 2178|回复: 0
打印 上一主题 下一主题

[技术资料] Android NDK项目崩溃信息抓取

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52696
    钢镚
    1422

    开源英雄守望者

    跳转到指定楼层
    楼主
    发表于 2015-1-16 14:10:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 破晓 于 2015-1-16 14:12 编辑
    1. <span style="background-color: white;">cocos2d-x lua binding,android-ndk-r9c,eclipse,cygwin,window7 64bit,red mi,Thl9,htc one</span>
    复制代码

    项目最近进入高速迭代阶段,版本更新速度比平时加快了几倍,这几天出的版本 莫名的出现频繁崩溃闪退的问题(仅仅Android上),不得已停下逻辑开发工作去fix 这个问题.

    问题重现

    打开游戏进入场景 频繁切换模块界面的时候 有一定几率崩溃

    初步猜测

    很大可能是加载销毁UI资源的时候导致C++代码出错.而仅仅在Android上出问题 就有可能是挂在异步加载的线程上.由于 最近两周才做的UI资源分模块管理 和异步加载.所以 异步子线程出的问题非常大.

    这个问题的难点在于,C++代码在android上调试比较困难,由于我们的项目(cocos2d-x lua)并非单纯的NDK项目 所以并不能完全用单步调试JNI的方式解决.需要知道问题的根源 还是必须从想办法抓取崩溃最后的打印信息开始.


    • LogCat打印内容

    在游戏崩溃的时候可以轻易跟踪到打印出最后两句内容:

    1. mtk_dlmalloc_debug DEBUG_INFO]FUNCTION internal_inspect_all Line ....略
    2. libc - Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 6034 (Thread-531)
    复制代码
    这种mtk_dlmalloc_debug信息 从libc库中引发,初步猜想是从用户层的原生库ibc.so引发.但是仅仅从这两句log来看 并不能十分确认问题的所在. 下面我们换一种方式抓取.
    • ndk-stack工具抓取
    ndk-stack工具的使用对于源码调试非常有用,如果是项目本身的代码(非底层原生库)出BUG的话,崩溃的时候甚至能打印出代码的行数.抓取命令:
    1. adb logcat | ndk-stack -sym "E:\rect\SrcClient\Game\proj.android\obj\local\armeabi-v7a"
    复制代码
    要点在于 编译C++代码的时候打开所有DEBUG选项,包括NDK的 NDK_DEBUG = 1 个人建议把V=1也加上,这样在eclipse编译C++代码的时候 能把所有NDK命令都打印出来.对于我这种命令行控来说 再好不过.通过ndk-stack 在 游戏崩溃的时候抓到如下内容
    1. ********** Crash dump: **********
    2. Build fingerprint: 'Xiaomi/2013022/HM2013022:4.2.1/HM2013022/JHACNBF17.0:user/release-keys'
    3. pid: 5555, tid: 5578, name: Thread-486  >>> com.cmge.onepiece < <<
    4. signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
    5. Stack frame I/DEBUG   ( 5612):     #00  pc 000246a8  /system/lib/libc.so: Routine ??
    6. ??:0
    7. Stack frame I/DEBUG   ( 5612):     #01  pc 00016cac  /system/lib/libc.so (dlmalloc+4908): Routine ??
    8. ??:0
    9. Stack frame I/DEBUG   ( 5612):     #02  pc 0000cb6c  /system/lib/libc.so (malloc+16): Routine ??
    10. ??:0
    11. Stack frame I/DEBUG   ( 5612):     #03  pc 00dc6a88  /data/app-lib/com.aaa.bbb-1/libogame.so (operator new(unsigned int)+24): Routi
    12. ne operator new(unsigned int) at ??:?
    13. Stack frame I/AEE/AED ( 5612):     #00  pc 000246a8  /system/lib/libc.so: Routine ??
    14. ??:0
    15. Stack frame I/AEE/AED ( 5612):     #01  pc 00016cac  /system/lib/libc.so (dlmalloc+4908): Routine ??
    16. ??:0
    17. Stack frame I/AEE/AED ( 5612):     #02  pc 0000cb6c  /system/lib/libc.so (malloc+16): Routine ??
    18. ??:0
    19. Stack frame I/AEE/AED ( 5612):     #03  pc 00dc6a88  /data/app-lib/com.aaa.bbb-1/libgame.so (operator new(unsigned int)+24): Routi
    20. ne operator new(unsigned int) at ??:?
    复制代码
    这个log传递给我们的信息比之前的丰富多了.我们几乎可以确认 这个崩溃和内存的申请释放有关,从
    1. operator new(unsigned int)+24
    复制代码
    来看 有可能是在new某块内存的时候引发的崩溃, 不一定是 unsigned int,因为我猜测很多时候翻译为int是不准确的.可能是玩的反编译多了 我很不信任翻译为int的内容. 目前为止我们能确认 和内存有关,但是并没有证据证明和线程有关系,所以必须有最后一步:NDK-GDB尝试调试.
    • ndk-gdb调试
    ndk-gdb是NDK提供的一个调试工具,我之前并没有用过它.所以在正确使用这个工具之前遇到了几个问题,在这里记录一下,由于工具在win平台上需要使用到cygwin,所以第一步是配置cygwin.第二步是使用ndk-build生成可供ndk-gdb调试的文件,第三步才是进行调试
    配置Cygwin
    例如我的加入环境变量
    1. NDK_MODULE_PATH =
    2. /cygdrive/e/rect/SrcClient:/cygdrive/e/rect/SrcClient/cocos2dx/platform/third_party/android/prebuilt
    复制代码
    修改.bash_profile,例如我本地的:
    1. ANDROID_NDK_ROOT=/cygdrive/e/rect/android-ndk-r9c
    2. export ANDROID_NDK_ROOT

    3. NDK_MODULE_PATH = /cygdrive/e/rect/SrcClient:/cygdrive/e/rect/SrcClient/cocos2dx/platform/third_party/android/prebuilt
    4. export NDK_MODULE_PATH
    复制代码
    此全部配置完毕.
    NDK-BUILD命令行编译C++
    命令如下
    1. ndk-build clean all NDK_DEBUG=1
    复制代码
    lean all 的意思是 编译之前先清理全部上次生成的内容,如果不加这个参数 则会报 patten %之类的错误.NDK_DEBUG=1 意思是生成调试版本的文件.加了这个参数后 调试的时候能定位到源码行数.整个编译过程大约持续30分钟.
    NDK-GDB 调试
    调试命令为(需手机连接电脑,并且在手机上运行游戏)
    1. ndk-gdb --verbose
    复制代码
    NDK-GDB这个工具略坑,在正常工作之前 抽了几次风.
    抽风之一
    ndk-gdb Could not extract package’s data directory. Are you sure that your installed application is debuggable?

    解决:修改ndk根目录下的ndk-gdb文件
    old:adb_var_shell2 DATA_DIR run-as $PACKAGE_NAME /system/bin/sh -c pwd
    newATA_DIR=”/data/data/$PACKAGE_NAME”

    抽风之二
    gdb.setp 生成的源码路径错乱,就像下面这样

    1. $ ndk-gdb --verbose
    2. Android NDK installation path: /cygdrive/e/rect/android-ndk-r9c
    3. Using default adb command: /cygdrive/e/rect/adt-bundle-windows/sdk/platform-tools/adb
    4. ADB version found: Android Debug Bridge version 1.0.31
    5. Using ADB flags:
    6. Using JDB command: /cygdrive/c/Program Files/Java/jdk1.7.0_51/bin/jdb
    7. Using auto-detected project path: .
    8. Found package name: com..aaa.bbb
    9. ABIs targetted by application: armeabi-v7a armeabi
    10. Device API Level: 10
    11. Device CPU ABIs: armeabi-v7a armeabi
    12. Compatible device ABI: armeabi-v7a
    13. Using gdb setup init: ./libs/armeabi-v7a/gdb.setup
    14. Using toolchain prefix: /cygdrive/e/rect/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/arm-linux-androideabi-
    15. Using app out directory: ./obj/local/armeabi-v7a
    16. Found debuggable flag: true
    17. Found data directory: '/data/data/com..aaa.bbb'
    18. Found device gdbserver: /data/data/com..aaa.bbb/lib/gdbserver
    19. Found running PID: 8351
    20. Launched gdbserver succesfully.
    21. Setup network redirection
    22. ## COMMAND: adb_cmd shell run-as com.cmge.onepiece /data/data/com.aaa.bbb/lib/gdbserver +debug-socket --attach 8351
    23. ## COMMAND: adb_cmd forward tcp:5039 localfilesystem:/data/data/com.aaa.bbb/debug-socket
    24. run-as: Package 'com.cmge.onepiece' has corrupt installation
    25. ## COMMAND: adb_cmd pull /system/bin/app_process obj/local/armeabi-v7a/app_process
    26. 89 KB/s (5736 bytes in 0.062s)
    27. Pulled app_process from device/emulator.
    28. ## COMMAND: adb_cmd pull /system/bin/linker obj/local/armeabi-v7a/linker
    29. 2468 KB/s (39436 bytes in 0.015s)
    30. Pulled linker from device/emulator.
    31. ## COMMAND: adb_cmd pull /system/lib/libc.so obj/local/armeabi-v7a/libc.so
    32. 5943 KB/s (273912 bytes in 0.045s)
    33. Pulled libc.so from device/emulator.
    34. /cygdrive/e/rect/android-ndk-r9c/ndk-gdb: line 770: [: armeabi-v7a: unary operator expected
    35. GNU gdb (GDB) 7.3.1-gg2
    36. Copyright (C) 2011 Free Software Foundation, Inc.
    37. License GPLv3+: GNU GPL version 3 or later
    38. This is free software: you are free to change and redistribute it.
    39. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    40. and "show warranty" for details.
    41. This GDB was configured as "--host=x86_64-pc-mingw32msvc --target=arm-linux-android".
    42. For bug reporting instructions, please see:
    43. .
    44. Warning: E:/rect/SrcClient/lua/proj.android/../../../cocos2dx: No such file or directory.
    45. Warning: E:/rect/SrcClient/lua/proj.android/../../../cocos2dx/include: No such file or directory.
    46. Warning: E:/rect/SrcClient/lua/proj.android/../../../cocos2dx/platform: No such file or directory.
    47. Warning: E:/rect/SrcClient/lua/proj.android/../../../cocos2dx/platform/android: No such file or directory.
    48. Warning: E:/rect/SrcClient/lua/proj.android/../../../cocos2dx/kazmath/include: No such file or directory.
    49. Warning: E:/rect/SrcClient/lua/proj.android/../../../CocosDenshion/include: No such file or directory.
    50. Warning: E:/rect/SrcClient/lua/proj.android/../../../extensions: No such file or directory.
    51. Warning: E:/rect/SrcClient/BaseCore/../../../include: No such file or directory.
    52. Warning: E:/rect/SrcClient/BaseCore/../../../Common: No such file or directory.
    53. Warning: E:/rect/SrcClient/BaseCore/filesystembzip2: No such file or directory.
    54. Warning: E:/rect/SrcClient/GameWnd/GameWnd: No such file or directory.
    55. Warning: E:/rect/SrcClient/EmBattleClient/Classes: No such file or directory.
    56. Warning: E:/rect/SrcClient/ArenaClient/Classes: No such file or directory.
    57. Warning: E:/rect/SrcClient/CardSystem/Classes: No such file or directory.
    58. Warning: E:/rect/SrcClient/DramaticClient/Classes: No such file or directory.
    59. Warning: E:/rect/SrcClient/EntityClient/Classes: No such file or directory.
    60. Warning: E:/rect/SrcClient/FightSystem/Classes: No such file or directory.
    61. Warning: E:/rect/SrcClient/ShipClient/Classes: No such file or directory.
    62. Warning: E:/rect/SrcClient/WorldBossClient/Classes: No such file or directory.
    63. Warning: E:/rect/SrcClient/Log/Classes: No such file or directory.
    64. Warning: E:\rect\SrcClient\Game\proj.android/jni/../../../../../Common: No such file or directory.
    65. Warning: E:\rect\SrcClient\Game\proj.android/jni/../../../../../Include: No such file or directory.
    66. Warning: E:/rect/SrcClient/engine/inc/common: No such file or directory.
    67. Warning: E:/rect/SrcClient/engine/inc/common/jsons: No such file or directory.
    68. Warning: E:/rect/SrcClient/engine/inc/engine: No such file or directory.
    69. Warning: E:/rect/SrcClient/engine/inc/render: No such file or directory.
    70. Warning: E:/rect/SrcClient/SkillSystem/GameWnd: No such file or directory.
    71. (gdb) obj/local/armeabi-v7a/gdb.setup:4: Error in sourced command file:
    72. Remote communication error.  Target disconnected.: No error.
    复制代码
    最后的一堆Warning 生成的都是错乱的路径.但是仔细看其实这是两个错误, 一个是错误路径,一个是无效路径.

    解决
    1.修改所有android.mk 把无效的源码路径全部去掉,大概修改了二十多个地方.
    2.对于几个错乱的路径 用完整路径代替.

    关于这个gdb.setup的路径生成BUG 我提在stackoverflowndk-gdb的问题解决了之后 再次运行调试命令.运行之后 输入
    1. continue
    复制代码
    该命令和VS的F5无意.然后 把之前的项目BUG设法重现.终于最后获取了最实在的堆栈信息:
    1. [New Thread 4285]

    2. Program received signal SIGSEGV, Segmentation fault.
    3. [Switching to Thread 4285]
    4. 0x400926a8 in ?? () from E:/rect/SrcClient/Game/proj.android/obj/local/armeabi-v7a/libc.so
    5. (gdb) bt
    6. #0  0x400926a8 in ?? () from E:/rect/SrcClient/Game/proj.android/obj/local/armeabi-v7a/libc.so
    7. #1  0x40089614 in dlmalloc_inspect_all () from E:/rect/SrcClient/Game/proj.android/obj/local/armeabi-v7a/libc.so
    8. #2  0x41613a6c in ?? ()
    9. #3  0x41613a6c in ?? ()
    10. Backtrace stopped: previous frame identical to this frame (corrupt stack?)
    复制代码
    bt命令可以查看最近的堆栈信息,输入bt后输出了比较实在的内容.从信息上看,大概流程是:
    新建线程切换线程调用dlmalloc_inspect_all (dlmalloc 我猜测是 delete malloc 清除内存). – 程序崩溃

    总结
    经过这几种方式取得的崩溃信息,粗略可以认为是 在 模块切换的时候 UI资源加载移除引发的 io操作 导致了 android虚拟机的频繁GC.有可能是GC到空的内容了.具体的解决方式 是建议把资源分块加载,例如有图片 A,B,C,D,E ,可以设定一个顺序 先后加载. 这个方法是否可行有待实验.over

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
    收藏收藏 分享分享 支持支持 反对反对 微信
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2024-4-20 21:08 , Processed in 0.057998 second(s), 36 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表