动态内存开辟 malloc calloc realloc free 函数
一、malloc和free
malloc和free都是c语言的库函数,一般在stdlib.h中,主要用来进行一段动态内存的分配,包括申请和释放。
malloc的函数原型为Void *malloc(size_t size),主要用于从堆上进行一段内存的申请,返回无类型的指针,需要将返回的指针转换为数据的类型,同时对申请的数据不进行初始化。
free用于将一段指针所指向的内存进行释放,free(p);由于通过malloc申请的内存在系统中记录了长度,因此不需要传入内存的长度。
二、malloc、calloc和realloc的比较
malloc的功能如上所述,calloc是用来进行堆空间的内存申请, 函数原型为void *calloc(size_t numElements,size_t sizeOfElement);参数为申请内存元数的个数,以及类型的长度,因此不必计算所要分配的内存的总字节数,同时alloc会对申请的内存进行初始化为0;
malloc和calloc所申请的内存均位于堆空间。malloc由于不需要对所申请的内存进行初始化,因此比calloc的效率要高。
realloc相当于改变指向动态内存区的指针的指向,让它指向新的动态内存地址;函数原型为extern void *realloc(void *mem_address, unsigned int newsize);一般分配了内存之后,如果重新分配内存,当之前分配的内存够用时指针不变,但要分配更大的内存空间时,采用尾部扩展的方式和新开辟一块内存(数据移动了),并返回内存首地址的指针。
#define MEM_BLOCK_SIZE 4096
#define MEM_LARGE_BLOCK_THRESHOLD 40960 //>MEM_LARGE_BLOCK_THRESHOLD :requested size is large block
#define MEM_BASE_ADDRESS (0x90000000)
#define MEM_ALLOC_TABLE_FIRST_ENTRY 0
#define MAX_MEM_SIZE 7*1024*1024
#define MEM_ALLOC_TABLE_SIZE (MAX_MEM_SIZE/MEM_BLOCK_SIZE)
static INT16 memory_map[MEM_ALLOC_TABLE_SIZE];
static char isMemoryManagementReady=0;
void *memset(void *s, int c, size_t count)
{
char *xs = s;
while (count--)
*xs++ = c;
return s;
}
INT32 ssd_mem_init(void)
{
memset(memory_map, 0, sizeof(memory_map));
isMemoryManagementReady=1;
}
INT16 ssd_mem_percentage_used()
{
int used=0;
int i;
for(i=0;i<MEM_ALLOC_TABLE_SIZE;i++)
{
if(memory_map[i])
{
used++;
}
}
return used*100/MEM_ALLOC_TABLE_SIZE;
}
//return -1:FAIL
//>=0: return allocated address offset
INT32 ssd_mem_malloc(UINT32 size)
{
int offset=0;
int startEntry=MEM_ALLOC_TABLE_FIRST_ENTRY;
int nmemb;
int i;
if(!isMemoryManagementReady)
{
ssd_mem_init();
}
if(size==0)
{
return -1;
}
nmemb=size/MEM_BLOCK_SIZE;
if(size%MEM_BLOCK_SIZE)
{
nmemb++;
}
if(size > MEM_LARGE_BLOCK_THRESHOLD)
{
for(offset=startEntry;offset<MEM_ALLOC_TABLE_SIZE-nmemb;offset++)
{
if(!memory_map[offset])
{
int vacantSize=0;
for(vacantSize=0;vacantSize<nmemb && !memory_map[offset+vacantSize];vacantSize++);
if(vacantSize==nmemb)
{
for(i=0;i<nmemb;i++)
{
memory_map[offset+i]=nmemb;
}
return (offset*MEM_BLOCK_SIZE);
}
}
}
}
else
{
for(offset=MEM_ALLOC_TABLE_SIZE-1;offset>=0;offset--)
{
if(!memory_map[offset] && ((offset+nmemb)<=MEM_ALLOC_TABLE_SIZE))//search start of vacant block
{
int vacantSize=0;
for(vacantSize=0;vacantSize<nmemb && !memory_map[offset+vacantSize];vacantSize++);
if(vacantSize==nmemb)
{
for(i=0;i<nmemb;i++)
{
memory_map[offset+i]=nmemb;
}
return (offset*MEM_BLOCK_SIZE);
}
}
}
}
puts("malloc size erorr=");
putInt32(size);
return -1;
}
//return 0:OK
//return 1:Out of bound
INT32 ssd_mem_free(INT32 offset)
{
int i;
if(!isMemoryManagementReady)
{
ssd_mem_init();
return 1;
}
if(offset<MAX_MEM_SIZE)
{
int index=offset/MEM_BLOCK_SIZE;
int nmemb=memory_map[index];
for(i=0;i<nmemb;i++)
{
memory_map[index+i]=0;
}
return 0;
}
else
{
return 1;//out of bound
}
}
void free(void *ptr)
{
if(ptr==NULL)
return;
INT32 offset;
offset=ptr-MEM_BASE_ADDRESS;
ssd_mem_free(offset);
}
void * malloc(UINT32 size)
{
INT32 offset;
offset=ssd_mem_malloc(size);
if(offset==-1)
{
return NULL;
}
else
return MEM_BASE_ADDRESS+offset;
}
void *realloc(void *ptr,UINT32 size)
{
INT32 offset;
offset=ssd_mem_malloc(size);
if(offset==-1)
{
puts("realloc error/n");
return NULL;
}
else
{
memcpy((void*)(MEM_BASE_ADDRESS+offset),ptr,size);
free(ptr);
return MEM_BASE_ADDRESS+offset;
}
}