bugly崩溃排查3:观察是谁调用了崩溃函数

简介: bugly崩溃排查3:观察是谁调用了崩溃函数

思路梳理

基本上lj_meta_cache造成的崩溃,是没有复现的希望了,毕竟luajit都好几年的代码了,而且使用的人非常多,所以问题不在luajit,请不要怀疑luajit作者的能力,大概率是项目的使用方式不当导致的。

所以排查方向也要发生变化,我们不能盯着luajit的源码,阅读理解源码细节解决问题基本不现实,毕竟luajit用来学习还行,但是要看明白,不是一时半会的事情,我简单看了看都涉及到lua语法分析、反汇编等各种非常基础的知识点,另外jit也是一门非常深奥的学科,基本上像c#,java,js都有类似的技术。

既然无法找到原因,那么只能考虑从调用信息上下手,统计出来都是谁在调用这个函数,然后尝试从lua代码层反推可能得原因,目前看来这是一个非常靠谱的解决办法。

将编译好的luajit移植到cocos2dx

我自己将luajit通过gitaction自动打包了一个版本,看luajit源码一时半会也找不到原因,考虑直接将luajit搞到项目里面

cocos2dx在window上默认使用的也是luajit

image.png

这样子问题就非常棘手了,我们编译出来的luajit仅仅是和cocos2dx自带的不同而已,但项目在windows上开发过程中,从来没有遇到luajit相关的任何崩溃,说明可能是平台差异导致的问题。

这里我们注意到了,luajit的编译过程,有生成对应平台的反汇编代码的步骤,所以这可能也是导致这个崩溃问题无法在windows上出现。

具体的集成过程不再赘述,简单来说我们只需要将debug版本的lua51.dll替换即可。

需要注意的是,为了得到更精确的调试信息,我们需要将/O2改为/Od

bash
复制代码
cl /nologo /c /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE
cl /nologo /c /Od /W3 /D_CRT_SECURE_NO_DEPRECATE

这是cl的编译选项,对应的vs项目属性是

image.png

调用信息

将debug版本集成到项目中后,运行调试看到了更深层次调用lj_meta_cache的逻辑

image.png

因为通过反汇编我们是观察到52行更加容易崩溃,所以我们在此处下断点,观察整个调用栈

image.png

竟然还能看到lua的相关变量

image.png

在目标函数设置钩子

因为调用量非常大,可以考虑将经过该函数的调用栈整理出来,然后统计汇总,再回过头review相关的游戏代码,进行排查,具体做法如下:

  1. 在luajit中定义一个全局的函数指针,项目中我们会实际设置这个回调函数,用来做相关的堆栈收集等处理
1. c
2. 复制代码
#ifndef __LIBHOOK__
#define __LIBHOOK__
#ifdef __cplusplus
extern "C" {
#endif
void (*hookFunction)();
extern __declspec(dllexport) void setHookFunction(void(*func));
void emitHookFunction();
#ifdef __cplusplus
}
#endif
#endif
  1. 在目标函数lj_meta_chche中调用这个回调,这样当执行到lj_meta_chche时,就会触发回调
1. c
2. 复制代码
/* Negative caching of a few fast metamethods. See the lj_meta_fast() macro. */
cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name)
{
  cTValue *mo = lj_tab_getstr(mt, name);
  lj_assertX(mm <= MM_FAST, "bad metamethod %d", mm);
  if (!mo || tvisnil(mo)) {  /* No metamethod? */
    emitHookFunction(); // 钩子函数在这里
    mt->nomm |= (uint8_t)(1u<<mm);  /* Set negative cache flag. */
    return NULL;
  }
  return mo;
}

这样对luajit的破坏是最小的,修改完毕后,需要重新编译下luajit。

将调用信息保存为log

cpp堆栈

c++的堆栈获取网上有很多例子,使用到的相关函数如下:

  • SymFromAddr检索指定地址的符号信息,成功返回TRUE,失败返回FALSE,并调用GetLastError获取错误码
  • SymGetLineFromAddr64查找指定地址的源行。
  • StackWalk,这个函数可以参考下

lua堆栈

注意,以上方式我们只能获取到c、c++层的调用堆栈,对于lua层的我们是拿不到的,在lj_meta_cache下断点,在vs自带的调用堆栈可以看到整个调用栈,不仅有c++ lua51.dll的堆栈信息, 还有lua_vm的堆栈

image.png

使用SymInitialize、SymFromAddr、SymGetLineFromAddr64,发现我是无法捕获到lua_vm层的堆栈信息的,CaptureStackBackTrace显示的堆栈数量比vs调用堆栈显示的少,怎么样才能捕获到lua_vm层堆栈

各种折腾,最后我发现是调用lua_getstack拿到的lua堆栈,正好和vs的对上了,这么看来vs ide底层在捕获堆栈,也有类似的处理,vs的确非常强。

完结

到这里,基本上我们已经尽可能的得到lj_meta_cache的相关信息了,剩下就是配套工具的开发去快速生成这个log文件。

反正最终也没有解决这个问题,只是尽可能的从代码层拿到了相关有用的信息,后续工作就是对log的分析和对相关lua代码定位的工作了。


目录
相关文章
PowerDesigner16(PDM)pd生成数据库sql脚本
今天使用PowerDesigner16软件生成数据库脚本的时候遇到了一些问题,但是经过不懈努力最终修成正果,下面将小编的经历以及错误解决方案与大家分享。
|
JSON 前端开发 Java
前端请求SpringBoot接口出现Required request body is missing
前端请求SpringBoot接口出现Required request body is missing
1060 2
|
7月前
|
Java 区块链 开发工具
模拟个人所得税APP,模拟计算Tezos智能合约
该项目基于Tezos区块链开发,旨在提供智能合约与自动化计算服务,主要技术栈包括智能合约编程语言与相关区块链开发工具。
995 0
|
7月前
|
存储 API 调度
养“虾”更高效:OpenClaw多Agent协同搭建+阿里云/本地部署+百炼api对接及避坑指南
2026年,OpenClaw(俗称“龙虾”,曾用名Clawdbot)的核心价值已从单一智能体执行升级为多Agent协同作战。单Agent模式在面对长流程、多任务场景时,极易出现上下文爆炸、任务排队、风格串味等问题,而多Agent团队通过“分工明确、隔离运行、协同调度”的模式,能完美解决这些痛点——就像一个专业团队,每个成员各司其职,在编排者的统筹下高效完成复杂任务。本文将从**多Agent团队搭建核心逻辑**、**阿里云+本地多系统部署步骤**、**阿里云百炼Coding Plan API配置**、**常见问题解答**四大板块出发,搭配可直接执行的代码命令和实操案例,实现OpenClaw从部署
1288 3
|
存储 缓存 运维
阿里云服务器经济型e与通用算力型u1实例各自性能、适用场景区别及选择参考
在选择阿里云服务器实例规格时,经济型e实例和通用算力型u1实例因其高性价比和广泛适用性,备受个人开发者、中小企业的青睐。在同地域、相同配置的情况下,经济型e和通用算力型u1实例的价格相对于其他实例规格要低一些,很多个人和初创企业用户都会优先考虑选择这两个实例规格的云服务器,那么它们之间有什么区别?各自的性能、适用场景上有何区别?我们应该如何选择呢?本文将详细解析这两款实例的性能特点、适用场景、价格优势及购买建议,帮助用户更好地理解并选择合适的云服务器实例。
918 17
|
安全 物联网 API
核验身份证的一致性API的实战指南
随着网络空间安全问题日益突出,实名制成为保障安全与秩序的重要手段。探数API的身份证实名认证工具通过姓名和身份证号核验用户身份真实性,并返回扩展信息,广泛应用于各行业。本文介绍了其实现功能、调用流程及代码示例,同时解答了关于个人信息安全等常见疑问。接入该API不仅满足合规要求,更能提升用户信任,降低运营风险,共同构建安全高效的数字未来。
1448 1
|
存储 前端开发 JavaScript
React 文件上传组件 File Upload
本文介绍了如何在 React 中实现文件上传组件,包括基本的概念、实现步骤、常见问题及解决方案。通过 `&lt;input type=&quot;file&quot;&gt;` 元素选择文件,使用 `fetch` 发送请求,处理文件类型和大小限制,以及多文件上传和进度条显示等高级功能,帮助开发者构建高效、可靠的文件上传组件。
1233 3
|
数据可视化 UED
移动应用的UI/UX设计原则与实践
【7月更文挑战第2天】移动应用UI/UX设计聚焦简约、一致性与用户中心原则。关键在于理解用户需求,创建清晰的视觉层次,实现响应式布局。UX关注反馈速度、情感连接及无障碍访问。通过用户调研、原型测试和持续迭代,提升满意度和产品竞争力。
1072 1
|
JSON fastjson Java
使用FastJson
使用FastJson
1297 1
|
存储 传感器 边缘计算
构建成功的边缘计算基础设施:硬件选择与关键接口
构建成功的边缘计算基础设施:硬件选择与关键接口
969 8