交互实验 01 · 从游戏看懂内存
阳光没变,地址怎么变了?
点击阳光、检查地址,再重启一次。把 C 代码里的 malloc、指针和结构体数组,和眼前的游戏连起来。
当前模拟进程RUN 0132 位教学模型 / 地址单位:字节
A游戏视图点击卡片 ↔ 选择数组元素
教学场景 · 点击下方按钮种植
选择一张植物卡片,观察它对应的数组元素。
界面只是数据的“显示窗口”
阳光数字读取 g_game->sun;第 i 张卡片读取 g_game->slots[i]。修改同一份数据,界面随即更新。
B与界面对应的 C 代码简化模型 · 32-bit
所有整数字段均为 4 字节;本模型指针为 4 字节。偏移以这里的结构体布局为准。
C进程内存地图示意图,不按真实地址比例绘制
D模拟地址检查器4 字节读取
写入 cooldown_ms 字段;下次种植时生效。当前剩余时间存放在另一个字段。
堆,是一片可按需申请的内存区域
malloc 向分配器申请字节,返回首地址。名字相同,但它不是数据结构课里用于优先队列的“二叉堆”。为什么这里选择堆?游戏状态要在初始化函数返回后继续存在,槽位数量也可运行时决定。堆便于管理这类对象的生命周期;这些值也可以采用其他存储方式,游戏数据并非必须放堆上。
连续的是数组,不是所有堆对象一次申请的
PlantSlot[N] 内部连续,每格固定 16 字节。两次独立 malloc 返回的区块不保证相邻,也不能靠固定差值互相寻找。模型边界:与真实游戏、CE 和 64 位程序有什么不同?
本页是独立、离线的内存模拟,不读取或修改任何真实进程。地址、结构体字段和偏移均为教学设计,不代表某个《植物大战僵尸》版本的逆向结果。真实对象也可能内嵌、来自对象池,或通过其他容器组织,必须核实布局后才能套用数组公式。
本页只模拟每次启动改变堆分配地址;全局指针变量的位置固定。真实系统的 ASLR 也可能改变模块基址,常以“模块基址 + 已验证的相对偏移”定位全局指针,再逐级读取。重启不保证地址必变,旧地址即使仍可读,也可能已经代表别的对象,不能证明它仍是阳光。
在 64 位 C 环境中,指针通常为 8 字节,结构体的对齐和填充也可能改变偏移。应使用 sizeof 与 offsetof 验证。这里数组直接保存结构体;若是指针数组,跨过一个指针后还需要解引用,不能直接照搬 16 字节步长。