/********************************************************************************************* 模块功能:ipanel内存分配释放。由于ipanel分配内存块较大,当操作系统内存碎片过多,且没有及时清理 的情况下,容易出现分配失败的情况,这时需要事先独立分配一块内存,提供给ipanel自身管理 模块描述:加入内存块头信息,存放分配内存块的大小、上下已用内存块头信息节点位置,采用链表管理 分配优先:检查memBaseAddr是否为第一节点(first),否,则尝试在memBaseAddr进行分配 -> 遍历链表,检查两已用内存块之间是否有可用空间,如有并大于等于分配大小,则进行分配 -> 在链表最后节点之后的剩余空间进行分配 改进权衡:
1、采用独立的空间存放内存块头信息 2、遍历所有已用内存块头信息链表,找到两已用内存块之间的可用空间最接近于要分配内存的大 小,并在该处进行分配,这样ipanel自身内存管理的碎片更少,但所耗的时间更长 3、直接在链表最后节点之后的剩余空间进行分配,当模块分配释放模式为malloc->malloc-> malloc->malloc->...->free->free->free->free时,推荐采用这种分配模式 *********************************************************************************************/ #include "stdafx.h" #include <stdio.h> #include <malloc.h>
void *memBaseAddr = NULL;//可分配内存的首地址 unsigned int totalMemSize = 0;//可分配内存的总大小
struct mem_block_info { unsigned int size;//等于实际分配内存大小加上结构体mem_block_info的大小 struct mem_block_info *preview;//存放上已用内存块的头信息节点位置 struct mem_block_info *next;//存放下已用内存块的头信息节点位置 }; struct mem_block_info *first = NULL;//链表头节点
/*初始化可分配内存的base address和memory size*/ void my_set_mem_base_addr(void *addr, int size) { memBaseAddr = addr; totalMemSize = size; }
/*释放已用内存,删除内存块头信息节点*/ void free_used_mem(struct mem_block_info *used) { if (used == first) first = first->next; else used->preview->next = used->next; }
/*遍历链表,寻找可用空间。返回已分配空间头信息节点*/ struct mem_block_info *search_available_mem(unsigned int size /*[in]: 要求分配空间大小*/) { unsigned int freeSize; struct mem_block_info *result = NULL; struct mem_block_info *current = first; if (size % 4) size = (size/4 + 1) * 4; //强制四字节对齐
if (!first) { //当内存是第一次分配时 freeSize = totalMemSize; if (size + sizeof(struct mem_block_info) > freeSize) { result = NULL; return result; } else { result = (struct mem_block_info *)memBaseAddr; result->preview = NULL; result->next = NULL; result->size = size + sizeof(struct mem_block_info); first = result; return result; } } if (memBaseAddr != first) { //检查第一个节点是否从memBaseAddr开始,如果否,优先从memBaseAddr进行分配 freeSize = (unsigned int)first - (unsigned int)memBaseAddr; if (size + sizeof(struct mem_block_info) <= freeSize) { result = (struct mem_block_info *)memBaseAddr; result->preview = NULL; result->next = first; result->size = size + sizeof(struct mem_block_info); first = result; return result; } } while (current) { if (current->next == NULL) { //优先从两内存块节点之间的剩余空间分配,如果都没有足够空间,则从后面的剩余内存进行分配 freeSize = totalMemSize - ((unsigned int)current - (unsigned int)memBaseAddr + current->size); if (size + sizeof(struct mem_block_info) > freeSize) { result = NULL; return result; } else { result = (struct mem_block_info *)((unsigned int)current + current->size); result->preview = current; result->next = NULL; result->size = size + sizeof(struct mem_block_info); current->next = result; return result; } } else { //检查两块已分配的内存块之间是否有足够的空间,如果有,则分配 freeSize = (unsigned int)(current->next) - (unsigned int)current - current->size; if (size + sizeof(struct mem_block_info) <= freeSize) { result = (struct mem_block_info *)((unsigned int)current + current->size); result->size = size + sizeof(struct mem_block_info); result->preview = current; result->next = current->next; current->next = result; return result; } } //否,则继续遍历 current = current->next; } return result; }
void *my_malloc(int memsize) { struct mem_block_info *result = NULL; result = search_available_mem(memsize); if (!result) return NULL; return (void *)((unsigned int)result + sizeof(struct mem_block_info)); }
void my_free(void* memptr) { struct mem_block_info *used; if (memptr) { used = (struct mem_block_info *)((unsigned int)memptr - sizeof(struct mem_block_info)); free_used_mem(used); } }
int _tmain(int argc, _TCHAR* argv[]) { //测试程序 printf("struct mem_block_info size %d\n", sizeof(struct mem_block_info)); struct mem_block_info *rc; void *ptr = NULL; void *first = NULL; void *second = NULL; void *third = NULL; void *fourth = NULL; void *fineth = NULL; unsigned int totalmem = 0xa00000; ptr = (void *)malloc(totalmem); my_set_mem_base_addr(ptr, totalmem); first = my_malloc(0x10000); second = my_malloc(0x20000); third = my_malloc(0x40); my_free(second); fourth = my_malloc(0x800); my_free(first); fineth = my_malloc(0x40000); *(unsigned int *)fineth = 0x40; printf("*fineth 0x%x\n", *(unsigned int *)fineth); rc = (struct mem_block_info *)((unsigned int)fourth - sizeof(struct mem_block_info)); printf("fineth struct info: size 0x%x, next %p", rc->size, rc->next); return 0; }
|
PS:
|
近日又研究了一下Unix下的内存分配策略,才晓得常见的策略有:
first-fit、next-fit、best-fit、quick-fit
quick-fit速度快,但空间浪费大,明显不适合我们模块这种情形
best-fit内存碎片少,但时间消耗大,在内存紧张的情形下可用
first-fit是我如今采用的一个策略
next-fit我感觉比first-fit有很大的改进,特别适用于内存会被多次分配释放的情形 |
如果今后要进行改进的话,可以考虑将next-fit和best-fit结合
阅读(851) | 评论(0) | 转发(0) |