开发原生扩展程序的时候总会碰到这样那样的问题,比如在编译服务器上编译不通过或者应用里扩展程序无效等等.
通常一旦原生扩展程序在编译服务器上报错, 服务器控制台会给出所有的错误信息. 包括错误类型和哪个文件哪一行出的错. 同时 log.txt
日志文件也会被保存在编译文件夹当中.
一旦原生扩展的程序代码出了问题, 有一下途径可以找到问题所在.
当你的代码出现问题时, 有一些方法可以找到问题的根源.
最普通的就是使用 调试器
.
调试可以让你在代码中步进, 设置 断点
而且能在崩溃时冻结运行.
各个平台都有一些调试器.
各个工具可以用来调试特定平台应用:
有些时候, 需要在代码里加入 printf() 声明. 之后, 你就可以从设备上获取日志文件来分析它.
注意 Defold 的debug编译版本默认只输出 dmLog* 函数结果.
在 Android 上, 获取日志最简单办法是通过终端的 adb
.
还可以在 Android Studio 里使用 console
, 这俩是一样的.
如果你从 Android 日志中获得了跟踪堆栈, 你可能要使用 ndk-stack 来进行解析.
在 iOS 中, 你要使用 iTunes 或者 Xcode 来观察设备日志.
当 Defold 引擎硬崩溃时会保存一个 _crash
文件.
它包含了关于系统和崩溃的信息.
你可以使用 crash module 来读取这个文件.
建议你读取这个文件, 收集信息然后放送到自己适用的服务器上来归集数据.
adb 可以显示此文件在哪 (不同设备保存位置不同)
如果应用是 可调试的, 可以这样获取崩溃日志:
$ adb shell "run-as com.defold.adtest sh -c 'cat /data/data/com.defold.adtest/files/_crash'" > ./_crash
在 iTunes 中, 你可以 view/download 应用容器.
在 Xcode -> Devices
窗口中, 也可以选择崩溃日志
如果你从 _crash
文件或者日志文件获得了调用堆栈, 就可以开始解析它.
也就是把各个调用堆栈的地址转化为文件名和代码行, 这样有助于找到出问题的原因.
使调用堆栈匹配正确的引擎是很重要的. 否则很容易让你调试到不正确的地方.
而且, 如果编译时使用了原生扩展, 确保添加了 –with-symbols 选项
以便从编译服务器获取所需信息. 比如, 可以在 iOS/macOS 的编译文件 build.zip
里找到 dmengine.dSYM
文件夹.
Android/Linux 可运行文件已经包含了调试信息.
还有, 你要持有引擎的完整版. 这样有助于分析调试文件的调用堆栈.
从 build 文件夹获取
$ ls
解压缩:
$ unzip dmengine.apk -d dmengine_1_2_105
找到调用堆栈地址
也就是分析前的调用堆栈, 类似这样
#00 pc 00257224 libmy_game_name.so
其中 00257224 就是地址
解析地址
$ arm-linux-androideabi-addr2line -C -f -e dmengine_12_105/lib/armeabi-v7a/libdmengine.so _address
如果使用了原生扩展, 服务器会提供解析文件 (.dSYM) 给你 (使用 bob.jar 加 “–with-symbols” 选项)
$ unzip
如果未使用原生扩展, 下载解析文件:
$ wget http://d.defold.com/archive/
使用载入地址进行解析
如果, 简单的输入调用堆栈地址不管用 (即 载入地址 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)
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB