unity崩溃查找

unity崩溃查找

android崩溃日志收集

  • 直接使用logcat日志定位
    unity自己会捕获崩溃,然后在 logcat 输出崩溃堆栈,不管是 java、c#、c++ 崩溃都可以
    因此只要获得logcat日志,就能获得崩溃堆栈

    1. 使用logcat获得日志
    2. 使用dropbox获得日志
    3. 使用bugreport获得日志
  • 手动转储崩溃日志
    主要考虑3个部分:

    • c# 异常
      这一部分已经被unity处理,会通过 Debug.Log 打印,只需要通过 Application.logMessageReceived 捕获日志并写入文件即可
      原理参考 捕获全局异常
      代码参考 unity日志输出到文件
    • java 异常
      可以使用 Thread.setDefaultUncaughtExceptionHandler 捕获 java 异常并写入文件中
      原理参考 用代码捕获android崩溃日志
      代码参考 unity崩溃输出到文件
    • c++ 异常
      这一部分已经被unity处理,会转成 java 异常抛出,所以不需要额外处理

ios崩溃日志收集

  • 使用自带的崩溃日志

  • 手动转储崩溃日志

    • IOS只有C++和C#两层,对于C#来说,和Android是一模一样的,不用多说。
      对于C++这层,Unity已经为ios提供了一个crash report模块,他需要我们将工程生成好后,将 Classes/Crashreport.h 里面的 ENABLE_CUSTOM_CRASH_REPORTER 设置为1,
      这样在c++ crash后,unity会为我们生存crash文件,等下次启动后,可以通过crashreport这个模块访问这些dmp文件,这些dmp文件都是ios上的标准dmp文件,可以使用ios的开发工具symbolicatecrash来查看。
      unity内置的crash report其实也是采用了第三方的库plcrashreport来实现的,这个库在ios上的应用很多。
    • 另外对于ios,其实也提供了一个函数NSSetUncaughtExceptionHandler ,用来当那些未捕捉的异常发生时,进入这个处理,可以拦截一些东西,
      但是一些比如内存访问错误直接就退出了,不会进到这里,另外进到这里之后程序还是会退出,只是让我们可以记录一下,不过有了unity自带的crashreport 这个也就没啥用了。
    • 还有在unity对ios的c#运行中,在player setting里面有个对代码的运行优化,选择slow but safe 还是fast but no exception,如果选择前者,所有c#的执行错误都会像脚本一样被catch住,会报c#的exception,
      如果后者就不会,就直接不catch了,会造成程序退出,但是运行效率是高的,我们通常选择slow but safe。这是mono架构的特性。

调用堆栈地址还原成符号

  • 符号表介绍

    • 首先符号表根据使用的编译参数不同,分为2种,debug 和 public,都能把地址转成函数名,不同的是 debug 会多一些信息,要调试的话只能用 debug 符号表
      debug 符号表后缀为 .dbg.so, public 符号表后缀为 .sym.so,一般 unity 引擎只有 public 符号表,你的游戏逻辑会同时生成 debug 和 public 符号表
      在使用的时候要移除 .dbg 或 .sym 后缀,比如 libunity.sym.so 改成 libunity.so
    • 其次debug和release也会生成不同的符号表,所以一共有4种符号表,debug版本的debug、public符号表,release版本的debug、public符号表
  • 首先定位符号表位置

    • Android
      参考 Unity 用户手册 2020.3 (LTS)/平台开发/Android/构建 Android 应用程序/Android symbols
      • unity引擎只有public 符号表,位于
        /PlaybackEngines/AndroidPlayer/Variations///Symbols//
        开启 Strip Engine Code enabled 后,libunity 会生成一个裁剪后的符号表 /Temp/StagingArea/symbols//
      • 用户代码只有开启 IL2CPP ,才会有符号表
        Il2cpp.so 是游戏逻辑编译出来的,其符号表在打包工程时生成
        • Build Settings 勾选 Create symbols.zip
        • 打包后会在 apk 输出目录生成 {应用名称}-{内部版本号}-v{版本号}.symbols.zip,
          里面就包含 Il2cpp.so 的 public 和 debug 符号表,以及 libunity 经过代码裁剪后的public符号表
  • 然后使用符号表把地址转成函数
    假设堆栈是这样的

        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
    

    则通过以下命令可以获得 006d4960 对应的函数名称
    arm-linux-androideabi-addr2line -f -C -e {unity安装目录}/PlaybackEngines/AndroidPlayer/Variations/{mono或il2cpp}/Release/Symbols/armeabi-v7a/libunity.sym.so 006d4960
    -f - Show function names
    -C - Demangle function names
    -e - Set the input file name
    arm-linux-androideabi-addr2line 位于 {NDK安装目录}/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line

unity日志输出到文件

    [DefaultExecutionOrder(-10000)]
    public clas

猜你喜欢

转载自blog.csdn.net/qmladm/article/details/131030687
今日推荐