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:98b632d2452c4231d4bc17abeb90d432ba2b8d071af46fb0ddc14286ba9fa25220261021_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。