内存管理的一个实验

之所以会写这个程序是因为培训中有一课是 TDD test-driven devp , 先写测试后写程序,是一种比较神奇的编程方法,看似不可能,其实这样程序出错的可能性更小。如果大家对 TDD 有兴趣可以去看看其他的书,我就不讨论了。接下来要谈的 MemPool 是课中实践题目,但是由于系统是 linux ,搞的我晕头转向的(命令行操作路径切换),程序没怎么写, linux 的操作到时学会了一些,呵呵。

MemPool 是自己实现的一个内存管理的方法,主要的想法就是每次用户申请内存我们先分配给他,然后当用户释放时我们不调用 free ,而是把申请的内容保持起来,下次再申请直接把这个空间给用户。题目要求分配内存的大小必须是 8byte 对齐( 8 16 32… ),然后维护一个表格,实现 MemPool_Alloc uint size )和 MemPool_Free void*p )两个方法:

Size

Total

Free

Point

8

1

0

NIL

16

1

1

XXXXXX

32

0

0

NIL

Total 是已经申请的内存块数, Free 是当前空闲的快数, Point 指向一个空闲内存的单项链表, NIL 表示空。

题目咋看起来比较简单,只要每次用户调用 MemPool_Alloc 时检查下是否有空闲块,有就返回单链表的第一个元素,没有就申请一块内存;当调用 MemPool_Free 时,把这块内存链到单链表中就 ok 了。这里为了简单起见,把表格定死,假设只有 8 16 32 ,这 3 个大小,不定死的话就是把这个表格变为一个单项链表。

先说我自己最初的想法:定义 2 个结构体,一个表示表格的每一行,另一个表示每个内存块。刚开始写的很顺,后来写到 MemPool_Free 时问题就出来了。因为只传进来一个参数 void *p ,而我们要归还的话必须得知道这块内存的大小,那怎么知道那?这得取决于我们 MemPool_Alloc 是怎么实现的了,最后我实现的方法是每次新申请内存后就把这块内存链起来,再增加一个 bool bIsFree 选项。这样每次归还时我只要查找到这个 void*p 属于哪个 Memory, 然后就找到了属于哪个 Block ,再设置 bIsFree true ok 了。分配时查找哪个 Memory bIsFree true ,否则申请一个。虽然这样是可以的,但是总要全部查找一遍总觉得效率不高。后来我去问了公司里的一个同事,他是培训中写完程序。发现他的方法很好。

typedef struct  tagMemory

{

    bool bIsFree;

       void *pMem;// 这个是要我们返回给用户的

       struct  tagMemory *pNext;

}Memory;

typedef struct tagBlock

{

       //block size

       int nTotal;

       int nFree;

       Memory *pFreeHead;

}Block;

 

  同事的方法:先把结构体改一下, Memory bool bIsFree 去掉就可以了。因为我唯一遇到的问题就是不知道归还的内存的大小,那我们想办法知道就可以了。或许你也会想到调用系统 free 时不是也没指定它的大小么,是的,因为系统分配时纪录了该块内存的大小。现在我们的方法也是一样的,就是申请空间时多申请一个 int 类型大小的空间来保存空间的大小(其实也可以是其他类型够大就可以了), Alloc 时的关键代码如下:

Size

Mem

Void *p = malloc(sizeof int + size);

int *pInt = (int*)p;

*pInt = size;

p = (void*)(pInt+1);

return p;

这里有些对 void* 指针操作的注意事项,

1.        不能直接对 void* 类型的指针进行解引用(就是取里面的内容),因为编译器不知道 void* 指针指向类型的大小。

2.        不能对 void* 指针用 sizeof

3.        void* 指针和其他类型的指针可以互相转换(也不是绝对)

最终 Free 时的关键代码如下:

Free((void*)((int*)p-1));

 

其实这个类似 MemPool 的东西在《 c 语言接口与编程》里也有,只不过他是通过 hash 来查找的,大家有兴趣可以去看看。这段时间以后一直都在学习语言或者是没有接触过的技术,对于这种需要技巧(对我而言)的东西很久没写了,感觉不错,趁热就把它纪录下来。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值