游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2217|回复: 1

简单的游戏内存管理模块实现问题

[复制链接]

1

主题

2

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2016-11-29 19:40:31 | 显示全部楼层 |阅读模式
以前是一个理工两狗之一的机械狗,非计算机科班出身,半路出家程序狗,某一天一个同样半路出家的基友说一起开发一个2D游戏,好吧那就来甘吧。因为这个游戏设定中是比较简单,一个关卡是一个地图,一个地图一个地图的过,关卡由脚本文件定义。没有什么很复杂的内容,也不准备采用什么引擎,准备自己实现一个满足要求的引擎就行。目前准备实现一个简单的内存管理器在设计过程中出现了一些问题,想请高手帮忙指点下。

设想中内存管理模块是负责整个内存的分配和回收的。这个模块在初始化的时候会分配一块内存,用void*指向内存块起始地址,具体多大还没确定不过与问题没多大关系。
设想中还有对象管理模块和场景管理模块,对象管理模块负责所有对象的生成和回收,也就是需要和内存管理模块交互。场景管理模块负责管理一个关卡,读取脚本解析脚本内容,然后针对关卡或者说地图中的每一个对象都要向对象管理模块申请对象内存,进而设置相关属性值,在过了进入下一个地图时会将当前关卡对象内存返回到对象管理模块中。对象管理模块负责向内存管理模块申请和回收内存。也就是说真正分配内存的是内存管理模块。
内存管理模块.png
随手画的一个流程图,大体这三者之间内存分配和回收就是这样。之所以使用一个对象管理模块,是因为前一个关卡和下一个关卡可能会有很多相同的npc和怪物或者地图上的物品也可能是相同的,在加载过一次之后不想重新在加载,使用对象管理模块在场景管理模块返回关卡内存之后不会立刻把内存返回到内存管理模块中,而是在对象管理模块中用链表存储起来,如果场景管理模块在此申请生成某一个对象时,恰好该对象已经在对象管理模块中就直接返回该对象。之所这样做,是觉得每个显示的对象有些资源是需要从磁盘中加载,这个比较耗时间所以想尽可能削减这个开销。

对象管理模块在某一个时刻检查对象链表,查看每一个对象最近有没使用过,如果有就保留,如果没有就将该对象内存返回到内存管理模块中。
内存管理模块维护一个已分配内存块结构链表,内存块结构链表保存每块分配的内存的大小和起始地址。结构如下:
struct memoryused
{
int count;
bool used;
void *ptr;
};
count代表分配的内存块大小,used代表本内存块是否有用到(为什么有着字段后面有说明),ptr内存块的起始地址。
在每次分配内存的时候就将代表该内存块的结构加入到链表中。维护这样一个链表的原因如下:
一、因为用了对象管理模块,所以某些已使用的内存块之间可能有未使用的内存块(代表这块内存被对象管理模块返回到了内存管理模块中),如果used为true,则这块内存分配了,used=false,则这块内存被对象管理模块返回了。
二、对象管理模块向内存管理模块申请内存的时候,内存管理模块检查本链表中是否有count满足要求,同时used=false的内存块,如果有就返回该内存,如果没有在分配内存。
三、因为有对象管理模块在内存管理模块初始化时分配的大块内存中可能会有内存碎片,因此在某些时候内存管理模块会检查维护的链表,移动某些内存以便整理内存碎片。

问题就来了:
内存管理模块整理内存碎片,需要移动内存中的一些内存,这个时候对象管理模块与场景管理模块中维护的内存指针都会失效,因此需要有某种方法更新这些指针。这个问题我不知道该怎么做。难道是在struct memoryused结构中增加两个void**指针,指向对象管理模块和内存管理模块中的指针?
游戏引擎架构一书中提及可以使用智能指针和句柄,但是我不清楚该怎么实现。
欢迎拍砖。不喜勿扰。谢谢。

9

主题

80

帖子

378

积分

中级会员

Rank: 3Rank: 3

积分
378
QQ
发表于 2016-12-5 10:20:34 | 显示全部楼层
自己从头开发就会遇到各种内存、画图的问题。还好我选择了引擎。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-2-25 02:33

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表