Read this manual in English

原生代码调试

Defold 几经测试鲜有崩溃情况出现. 但是崩溃这种事谁能保证永远避免, 尤其是游戏中还使用了原生扩展代码的情况下. 要是游戏崩溃或者原生代码出错请从下面几方面入手检查:

  • 使用调试器调试代码
  • 使用 print 函数检查代码
  • 分析崩溃日志
  • 调用堆栈代码文件映射

使用调试器

首先推荐使用 调试器. 使用它步进代码, 设置 断点 最重要的是游戏崩溃时会自动暂停.

不同平台调试器有很多.

  • Visual studio - Windows
  • VSCode - Windows, macOS, Linux
  • Android Studio - Windows, macOS, Linux
  • Xcode - macOS
  • WinDBG - Windows
  • lldb / gdb - macOS, Linux, (Windows)
  • ios-deploy - macOS

每个工具可以调试的应用如下:

  • Visual studio - Windows + platforms supporting gdbserver (比如 Linux/Android)
  • VSCode - Windows, macOS (lldb), Linux (lldb/gdb) + platforms supporting gdbserver
  • Xcode - macOS, iOS (详见)
  • Android Studio - Android (详见)
  • WinDBG - Windows
  • lldb/gdb - macOS, Linux, (iOS)
  • ios-deploy - iOS (via lldb)

使用 print 函数

调试最简单的方法就是使用 print 函数. 位于 dmLog 命名空间 下的 print 函数可以用来检查变量值或者用来检查程序执行流程. 它可以在 控制台 视图和 游戏日志 中输出数据.

崩溃日志分析

崩溃时, Defold 引擎保存了一个 _crash 日志文件. 其中包含了系统信息与崩溃信息. 其存放位置参考 游戏日志输出 (不同设备, 系统, 位置不同).

可以使用 崩溃模块 帮助分析这个文件. 推荐你阅读, 收集信息, 打印信息到控制台, 然后把信息发送到 第三方分析服务 上去.

在 Windows 上还有个 _crash.dmp 文件被创建. 这个文件在调试崩溃时很有用.

从设备上获取崩溃日志

手机上的崩溃日志可以下载到本地以便查看.

Android

如果应用是 可调式的, 就可以使用 Android Debug Bridge (ADB) 工具adb shell 命令得到崩溃日志:

$ adb shell "run-as com.defold.example sh -c 'cat /data/data/com.defold.example/files/_crash'" > ./_crash

iOS

在 iTunes 里, 可以下载 app 容器.

Xcode -> Devices 窗口中也能获取到崩溃日志.

调用堆栈代码文件映射

_crash 文件或者 日志文件, 都可以进行代码文件映射. 即把调用堆栈里的每个地址映射到文件名和代码行, 利于寻找代码的问题.

注意引擎版本要选择正确. 不然映射会错乱. 使用 bob 编译时命令行加入 –with-symbols 或者在编辑器打包对话框里点选 “Generate debug symbols”:

  • iOS - 在 build/arm64-ios 下的 dmengine.dSYM.zip 中包含有 iOS 编译用 debug symbols.
  • macOS - 在 build/x86_64-macos 下的 dmengine.dSYM.zip 中包含有 macOS 编译用 debug symbols.
  • Android - 在打包输出目录 projecttitle.apk.symbols/lib/ 下包含有各架构编译用 debug symbols.
  • Linux - 可执行文件本身包含 debug symbols.
  • Windows - 在 build/x86_64-win32 下的 dmengine.pdb 中包含有 Windows 编译用 debug symbols.
  • HTML5 - 在 build/js-webbuild/wasm-web 下的 dmengine.js.symbols 中包含有 HTML5 编译用 debug symbols.

对于游戏的每个发布版本一定要保留一套对应的调试数据. 不然的话原生扩展上线以后出错误就没法调试! 为了方便查看调用堆栈, 也要保存好对应的游戏引擎.

把 symbols 上传到 Google Play

可以 上传 debug symbols 到 Google Play 以便让 Google Play 上的崩溃日志显示可读的调用堆栈. 详情请见 原生代码调试教程.

Android调用堆栈映射

  1. 从编译文件夹下找到引擎文件

    $ ls /build//[lib]dmengine[.exe|.so]

  2. 解压引擎:

    $ unzip dmengine.apk -d dmengine_1_2_105

  3. 找到地址

    例如下面这个文件

    #00 pc 00257224 libmy_game_name.so

    其中 00257224 就是地址

  4. 映射地址

    $ arm-linux-androideabi-addr2line -C -f -e dmengine_12_105/lib/armeabi-v7a/libdmengine.so _address

注意: 要是从 Android 日志 获取的调用堆栈数据, 可能需要使用 ndk-stack 进行地址解析

iOS 调用堆栈映射

  1. 如果使用了原生扩展, 服务器会为你提供映射数据 (.dSYM) 文件 (使用 bob.jar 连同 --with-symbols 参数)

    $ unzip /build/arm64-darwin/build.zip # 文件会被解压到 Contents/Resources/DWARF/dmengine

  2. 如果没用原生扩展, 直接下载映射文件:

    $ wget http://d.defold.com/archive//engine/arm64-darwin/dmengine.dSYM

  3. 地址映射

    不能直接使用堆栈里的地址 (比如载入地址 0x0)

     $ atos -arch arm64 -o Contents/Resources/DWARF/dmengine 0x1492c4
    

    # 也不能作为参数加入载入地址

     $ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp -l0x100000000 0x1492c4
    

    二者相加才可以:

     $ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp 0x1001492c4
     dmCrash::OnCrash(int) (in MyApp) (backtrace_execinfo.cpp:27)