# 背包「空格数量」误判 —— 根因分析 > 2026-10-12 01:10 | 角色「江南雨替我说别」(objID 9220 / 全服ID 1125) | 全部结论为 CE 实测 ## 一、现象 背包**实满 96/96**,助手却报「有 2 个空格」→ 判定为**未满** → 回补 / 存卖不触发 → 背包永远清不空。 助手自己的日志(手动点「取背包空格数量」): ``` 01:03:03 :背包空格数量:2(本次扫描格数:96) ``` ## 二、根因 **`遍历背包空格数量` 用「物品位置 ≤ 0」判空格,而物品对象指针可以 ≥ 0x80000000 —— 易语言「整数型」是有符号的,这种地址读出来是负数,于是被当成空格。** 客户端 `YGOnline.exe` 是 **LARGEADDRESSAWARE(3GB 感知)**,堆地址会越过 2GB 线。物品对象是逐个拾取时分配的,其中两个落到了高位区。 ## 三、证据 `背包容器 = 读dword(0x03BEF5D0) = 0x47B93EA8`,槽位数组 `容器 + 0x53C + 4×(槽位-1)`,实测 96 格指针: | 槽位 | 指针 | 易语言「整数型」读到的值 | 实际内容 | |---|---|---|---| | 1 | `0x6C27F0F0` | 1814499568(正) | 上級集魂珠(稀有) 编号1000000326 | | 8 | `0x6C274098` | 1814491288(正) | 熱血石 编号800000013 | | **52** | `0x828D7050` | **-2104659888(负)** | **熱血石 编号800000013** | | **53** | `0x828D4038` | **-2104672200(负)** | **熱血石 编号800000013** | | 54–70 | `0x6865A0C8`… | 1751xxxxxx(正) | 下級集魂珠(一般) 编号1000000321 | | 其余 91 格 | `0x6Cxx/0x6BDx/0x686x` | 均为正 | 各类真实物品 | - **异常格 = 恰好 2 格**(52、53),与助手报的「空格 2」**精确对应**。 - 这两格的对象**读得出合法编号与 BIG5 名称**(`熱血石` / 编号 `800000013`)⇒ 是**真物品,不是空格**。 - 判定点:`0x828D7050` 无符号 2190307408 → 有符号 **-2104659888** ≤ 0 ⇒ 命中「空格」分支。 ## 四、波及面(不止"背包满") 同一 `≤ 0` 判据在工程内共 **40+ 处**,按对象分类: | 目标对象 | 处数 | 后果 | |---|---|---| | `物品位置 ≤ 0`(背包物品) | ~25 | 高位地址的物品被当成空格/被跳过:**空格数量虚高**、**存仓/卖物/过滤集魂珠会漏掉这些格**(背包清不空) | | `背包位置 ≤ 0`(红蓝药等统计) | ~12 | 红/蓝药数量少算 → 误判药不够 | | `仓库位置 ≤ 0` | 1 | 仓库同上 | | `怪物位置 ≤ 0` | ~10 | **怪物对象一旦被分配到高位区就会被整只漏掉**(当前实测的怪都在 0x7Axxxxxx 以下,尚未触发,但是同一颗雷) | | `对象位置 / 该格位置 ≤ 0` | 3 | 遍历人物 / 逐格操作同上 | ## 五、修法 把「空指针」判据由 `≤ 0` 改为 `= 0`: ``` ' 旧:把 ≥0x80000000 的真物品指针当成空格 .如果真 (物品位置 ≤ 0) 空格数量 = 空格数量 + 1 到循环尾 () .如果真结束 ' 新:只有 0 才是空格 .如果真 (物品位置 = 0) 空格数量 = 空格数量 + 1 到循环尾 () .如果真结束 ``` - 空槽位存的就是 0,`= 0` 与 `≤ 0` 在「地址 < 2GB」时**行为完全一致**,不影响既有正确结果。 - 对高位地址:不再被误判成空格;且因为顺带跳过 `内存_读文本型`,**不会因脏指针去读非法内存**。 - 副作用方向是「少算空格」=更容易报「满」——正是本次期望的方向;最坏情况是回补白跑一趟,不会漏报满。