XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8

2026-10-21 游戏崩溃排查

本记录区分转储直接证实的故障、代码审查发现的问题和实机复测结果。原始转储只在本机分析,没有提交给第三方。自动导航完整功能仍未验收,不据此启用自动飞行。

转储结论

本机时间 游戏 PID / 崩溃线程 自有加载器 异常位置
08:13:36 23104 / 4596 0.2.0-dev,PE 时间戳 6ad802e9,映像大小 75000 游戏 RVA 552072,0xC0000005
08:15:44 63768 / 18140 已回退的 0.1.0,PE 时间戳 6ad7e392,映像大小 29000 游戏 RVA 55207D,0xC0000005

游戏 EXE 两次均为 r334473,SHA-256 6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93。加载器版本通过转储模块的 PE 时间戳和映像大小与已保存 DLL 交叉核验;转储自身不包含 DLL 文件的 SHA-256。

两处属于同一函数 RVA 551FC0:内存分配器分配新块时从空闲链表摘取节点。第一次链表指针含非规范地址,第二次链表节点的下一项为零,随后写入地址 0x18 触发异常。已确认空闲链表损坏;尚未确认更早的哪次写入破坏了它。 这不是仅凭异常代码判断内存不足。

调用栈由 Windows 自带 DbgEng 从异常上下文展开。游戏没有完整私有符号;调试器显示的远距离导出函数名称不能当作真实函数名,故本报告使用游戏 RVA。反编译通过固定构建间的唯一代码匹配核对,未改动游戏 EXE。

第二次使用旧加载器仍崩溃,不能把首次崩溃直接认定为新物理挂钩造成。现有转储也不能排除其他组件或启动时序的影响。没有为了继续运行而跳过游戏检查或覆盖分配器错误。

已修正的代码问题

这些是独立查实的实现缺陷或边界风险,不等同于已经证明了上述两次崩溃的写入来源。

  • 原加载器以 /MT 链接静态 CRT,却在 DllMain 中调用 DisableThreadLibraryCalls。已保留线程通知;微软明确要求静态 CRT DLL 不禁用它们,见 官方说明。
  • 使用 CRT 的服务线程改用 _beginthreadex,并在真正的系统 DirectInput 初始化成功后启动;服务失败不改变原始 DirectInput 返回值。见 线程运行时说明。
  • 安装和状态查询只启用通信。导航挂钩需要单独的 navigation.observe.start 请求;独立研究 DLL 也改为显式导出启动,DllMain 不创建线程。
  • 服务运行期间固定自有模块的生命周期,避免游戏释放输入包装 DLL 后线程或回调继续执行已卸载代码。停用与退出后清理仍由安装管理器执行。
  • 原生输入恢复改为每次调用独立保存,并再次验证实体编号、生命周期、输入对象及物理对象关联。原调用销毁或回收对象时不向旧地址恢复数值,玩家修改过的轴也不覆盖。
  • 姿态查询使用游戏已注册的接口编号,不再逐项探测固定的 512 个条目;当前玩家失效时立即撤销该帧有效性。
  • 原生安装失败不再重复尝试同一进程的部分安装,线程创建失败会停用自有挂钩。失败的重新预检也会清除 C# 缓存能力。
  • 生成匹配 DLL 的 PDB、MAP 和只含版本、PID、线程及生命周期阶段的本机日志。诊断工具的连接超时以错误退出,不再制造自身的未处理异常转储。

复测与验收状态

已保存的启动对照均未发送飞行指令,也没有读取屏幕:

对照 证据 结果
移除自有加载器,保留原汉化 startup-no-toolbox-01.json 连续存活 60 秒,正常关闭
重新安装原 0.1.0 startup-old-plugin-01.json 连续存活 60 秒,正常关闭
重新安装原始故障 DLL 0.2.0-dev startup-nav-plugin-original-01.json 连续存活 60 秒,正常关闭
加固版首轮 startup-hardened-01.json 连续存活 60 秒;状态查询后原生入口仍与磁盘一致
最终 DLL 第 1、2 轮 startup-hardened-final-01.json、startup-hardened-final-02.json 每轮连续存活 60 秒,均核对同一 DLL 哈希
最终 DLL 强制结束后重启 startup-hardened-final-after-force.json 连续存活 60 秒,没有新增崩溃转储

因此故障尚未稳定复现,不能用一次成功启动宣布根因已经消除。最终加固 DLL 的重复启动、显式观测结果和文件哈希另见 artifacts/crash-analysis-20261021/acceptance.json;缺少该文件或其中未通过的项目均不算验收通过。

显式观测已连续存活 84 秒,初始化成功,未发送驾驶轴或跃迁命令。随后一次 CloseMainWindow 未在 15 秒内结束进程,另外保存了诊断转储。展开栈及原生活动检查证明游戏仍在 MainMenu 正常更新(5 秒内 1199 次更新),不能把该关闭请求超时当成插件死锁。经同一自然游戏线程核对定义、缓存及 0x0101 可用状态后,调用一次原始 QuitApplication,进程结束,Journal 写入 Shutdown,没有新增崩溃转储。此项只验证主菜单中的原生退出,不代表游戏内重进已完成;大退仍按用户要求直接结束核对身份的进程。

核心回归共 155 项:151 通过,0 失败,4 项环境集成检查跳过。原生独立测试覆盖整数/SSE/标志保留,以及对象回收、玩家输入变化、物理关联变化和页面失效时的输入恢复边界。独立分配的测试内存结果不冒充实际自动飞行通过。

本机证据

原始转储的工作区副本和 SHA-256:

  • 20261021_081336_MiniDump.dmp:98b632d2452c4231d4bc17abeb90d432ba2b8d071af46fb0ddc14286ba9fa252
  • 20261021_081544_MiniDump.dmp:1ad65f48025e67c73f92962020482a2f952b303ed1d13146ce12520da53f6942

目录:artifacts/crash-analysis-20261021/。metadata.json 保存异常、模块及寄存器;*-debugger.txt 保存本机展开栈;allocator-map-d-to-e.json 与 allocator-decompile/ 保存分配器核对;startup-*.json 保存实际进程与组件哈希。stackPointerCandidates 只是原始栈指针候选,不能当作展开后的栈。

本次没有修改汉化 DLL、资源包或游戏 EXE。抓包保持被动,游戏退出后等待同一安装再次启动。

测试结束后,选定游戏及本次官方启动器均已关闭,自有开发加载器及安装记录已移除;下一版源码、DLL 和匹配符号保留在工作区,没有作为生产版本发布。cleanup.json 逐项核对游戏 EXE、汉化 DLL 与资源包仍为原哈希。被动采集守护已续开,最多 120 分钟、1024 MiB,当前等待所选游戏启动;最新目录和期限见 capture-renewal.json 及相应 status.json。