首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 驱动开发 >

c语言内存对其和内存碎片有关问题

2013-01-08 
c语言内存对其和内存碎片问题cpu使用stm32f107,编译用keil,网络应用,要求在网络不通的时候储存有效数据,到

c语言内存对其和内存碎片问题
cpu使用stm32f107,编译用keil,网络应用,要求在网络不通的时候储存有效数据,到一定程度循环存放,释放最老的数据包……
当初考虑过使用数组解决,但是因为每包数据长度不固定,使用数组也不是一个很好的办法;而且储存的数据多的时候使用数组处理起来更麻烦;使用此种方法是否会造成内存碎片及内存耗尽的情况?
struct LNODE
{

  u16 buflen;          //包长度
  u8  ref;                  //包标志,为1说明该包需要发送
  struct LNODE *next;         //下包地址
  u8 *payload;        //该包未发送数据指针
}
*not_sent_bufs; 
//缓存链表首地址

链表节点如上,payload为不定长数据包指针,其长度为buflen,为了避免内存碎片,想创建节点时把payload数据内存一并申请,即malloc(sizeof(struct LNODE)+buflen);同时payload指向数据区头部;可否如此
not_sent_bufs = malloc(sizeof(struct LNODE)+buflen);
not_sent_bufs ->payload = (unsigned char *)not_sent_bufs +sizeof(struct LNODE);  //
memcpy(not_sent_bufs ->payload,sbuf,buflen); //拷贝数据
……
加入节点到链表
……
[解决办法]
如果想避免在你的系统上碎片太多,申请开销延迟等问题,一开始就申请一段足够内存,自己再管理这段内存供你的模块使用。
自己管理这段内存,肯定也存在释放分配碎片的问题,不过可以根据你的情况使情况简化。
如果觉得还是麻烦,就申请固定长度的连续buffer,管理肯定简单,但缺点是可能浪费内存。。。

根据自己的情况选择合适的方法。。。
[解决办法]
好吧,给你点实用的。
原理很简单,无非是内存池,slab。
防止内存碎片和反复malloc/free的轻量实现:
http://www.codeproject.com/useritems/Small_Block_Allocator.asp

据我所知,著名的物理引擎box2d也是用这个来进行内存的高效管理的。
[解决办法]
看看MFC程序编程吧, 里面就有一个简单的内存池的实现方式, 想要不产生任何内存碎片很简单的, 只要每次分配的大小都跟页面大小一至, 这样就不会有碎片了. 创建出来的大块数据之后, 再划分成对应大小的每个小块, 连接起来成为Free链表, 申请时只要向Free链表查找有没有可用内存块, 有就直接返回, 没有就创建一个新的大块. 
内存池的方式都基本是这样子的.

例子里面也是说明了固定长度的内存池, 要做成非固定长度的内存池, 很简单的, 仅需要加个HASH表, HASH就直接用申请的大小作为KEY即可.
每个HASH都保存着对应的Free链表, 那么申请动态内存的时候, 仅需要查找HASH表, 找到对应的FREE链表, 为空时, 就创建一个大块, 并且把划分出来的所有小块加入当前KEY的Free链表即可.

这个就是基础型的内存池了. 

然后可以加入多一点的统计算法, 或者是直接加入固定的算法, 让经常使用的内存大小尽量减小释放所对应的内存块, 这样就可以提高不少速度了.
[解决办法]
只要方法用对,根本不用担心碎片问题,前面的朋友说了,在运行中千万不要用malloc,太不稳定,建议你直接在启动时预留一块内存用作存放空间,当然能用flash那就更好了,完全不用担心不够的问题,然后针对你分配的一块内存,自己实现一套分配管理接口,例如mallocnet(),freenet(),原理可以参考slab的实现,完全自己透明实现小块内存的管理,分配和释放,链表最好是双向的,用list_head,可以实现。

热点排行