/*********************************************************************************************
模块功能: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;
}
|