分析Lua在bugly上的报错

module ‘xxx’ not found: no field package.preload[xxx]


完整一点的报错信息:

1
2
3
4
5
6
7
8
9
10
11
12
module 'xxx' not found: 
no field package.preload['xxx']
no file './xxx.lua'
no file '/usr/local/share/luajit-2.1.0-beta2/xxx.lua'
no file '/usr/local/share/lua/5.1/xxx.lua'
no file '/usr/local/share/lua/5.1/xxx/init.lua'
no file '/data/user/0/xxx.lua'
no file '/data/user/0/xxx.lua'
no file '/data/user/0/xxx.lua'
no file './xxx.so'
no file '/usr/local/lib/lua/5.1/xxx.so'
no file '/usr/local...too long be cutted!

从字面意思来看,就是找不到名为xxx的lua模块。

问题来了,为什么安装包里的某个文件会不翼而飞呢?

是用户删掉了?还是包体不完整?

我这里遇到的情况是这样的:

这个名为xxx的lua文件,需要通过热更下载到用户的设备上。而热更新系统有一套方法来判断:

  • 哪些文件本地没有,因此需要从服务器上下载这个文件到用户设备上
  • 哪些文件本地和服务器上有差异,这个时候也需要重新下载这个文件替换本地的旧版本

一般来说,热更系统需要维护一个列表文件,通过这个文件它就可以回答上面的两个问题。

问题就出在这个列表文件上,列表文件是通过记录所有需要热更文件的md5码,来判定是否需要更新某个文件的。

而我的安装包里的列表文件记录了xxx.lua已经是最新了的,它的md5码和服务器上的一模一样。但是实际上本地根本没有这个叫做xxx.lua的文件。

根本上说,就是信息的元数据(热更系统维护的那个列表文件)和信息实体(xxx.lua文件),出现了差错,已经不一致了。

数据的元数据已经不能准确的反映它所指代的数据实体了。

才导致这样的错误。

定义的lua变量,无缘无故的就成nil值了,消失了。彷佛从来就没有过这个变量一样


出现这种情况的原因之一可能是:

热更或者其它相关系统或者开发工具,根本没有检测到你添加代码所作的改动,所以根本就没通过热更把你的最新代码下载到用户的设备上。

这个情况和我之前在C++开发环境下遇到过的有点类似。

我在某个cpp文件添加了一些代码,编译后,从运行效果来看,就好像根本没有我新添加的代码一样。

而且,编译时,发现visual studio输出窗口显示:没有检测到任何改动。。。

一般这种情况下,打开你添加代码的那个文件,按回车键,添加几个空行保存后,重新编译运行或者打包热更就好了。

loop or previous error loading module ‘xxx’


出现这个提示,有可能是以下两种情况造成的:

  • loop:两个模块,循环加载。

例如有moduleA和moduleB

moduleA.lua,这样写:

1
require("moduleB")

moduleB.lua,又这样写:

1
require("moduleA")

在C++里,可以使用class的前置声明,来解决两个头文件互相include而导致的问题

  • previous:调用未定义完的变量。在一个表的内部,某个变量调用了一个也是属于表内部的变量。在创建时整个表还压在栈中没完成创建,无法调用到。

理论上不可能出现的空值


出现这种情况,有段时间我也是挺郁闷的。

就我遇到的,有下面两种情况:

  • 调度器系统(scheduler system)搞的鬼:比如,让你的游戏进入场景后,立刻开启一个调度器,设定在若干秒后执行某段代码。正常情况没什么问题,但是,如果在调度器还没有开始执行,玩家就退出了这个场景。随后,调度器里的代码才被执行。这样就会导致大部分和场景生命周期相关的变量都是一个空值。包括那些看似如论如何都不可能为空的变量,比如场景本身。
  • 脚本出错,导致后续逻辑没有执行(包括初始化某些变量的逻辑):脚本出错一般不会导致app闪退,然后这个时候玩家点击某个按钮,响应事件里的代码一旦使用到了那些因为脚本出错根本没有进行初始化的变量时,也会导致表面上看似无论如何都不可能为空值得变量。