要想使用malloc,至少要经过两步:
第一 建立线性内存空间管理表,将线性内存分成若干个段,除开一些特殊的段外,存在一些自由的段;
第二 从自由段中抽取一块作为堆,堆初始化后,就可以通过malloc函数申请变量的存储空间了。
堆可以有多个,,共享系统程序空间应建立至少一个堆,进程中也可以建立多个。
malloc函数应给定堆的指针
void *mem_heap_create(PMEMORY_BASIC_INFORMATION pMBI ,DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
{
void* heap;
PMEM_CONTROL_BLOCK mcb;
heap=mem_virtual_alloc(pMBI,0,dwInitialSize,MEM_COMMIT,PAGE_EXECUTE_WRITECOPY);
print_farmat_msg("mem_heap_create: %x,%x \n",heap,dwInitialSize);
//设置堆的头部参数,current_blocksize整个堆的大小
mcb = (PMEM_CONTROL_BLOCK)heap;
mcb->is_available = 0;
mcb->prior_block = (void*)-1; //标识堆头
//mcb->current_blocksize =dwInitialSize ;
mcb->heap_end=(DWORD)heap+dwInitialSize;
mcb++;
//第一个块
mcb->is_available = 1;
mcb->prior_block = heap; //标识第一块
mcb->current_blocksize =(dwInitialSize - (sizeof(MEM_CONTROL_BLOCK)+ sizeof(MEM_CONTROL_BLOCK)));
return heap;
}
//从堆中分配内存
void *mem_heap_alloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
{//lb 0x80404843
//unsigned int current_location;
int use_size;
void * return_pointer = 0;
/* 这与current_location相同,但转换为memory_control_block */
PMEM_CONTROL_BLOCK current_mcb = NULL;
PMEM_CONTROL_BLOCK other_mcb = NULL;
_ALIGN(dwBytes,4);
/* variable用于保存返回值并设置为0,直到我们找到合适的值 */
// 从托管内存开始搜索
current_mcb = hHeap+sizeof(MEM_CONTROL_BLOCK);
use_size=dwBytes+sizeof(MEM_CONTROL_BLOCK);
//遍历所有块,找到合适的空闲块
while((DWORD)current_mcb <((PMEM_CONTROL_BLOCK) hHeap)->heap_end)
{
//判断当前区块是否可用 ,不可用查找下一个,当前块未被使用
if(current_mcb->is_available)
{
// print_farmat_msg(" %d %d",current_mcb->current_blocksize,dwBytes);
//判断当前块大小是符合需要
if(current_mcb->current_blocksize<dwBytes)
{
//1、当前块小于需要量,查找下一个
goto nextblock;
}
else
{
//2、大小正合适,直接将当前地址返回
//3、当前块大于需要量,但分割后的空间小于或等于MEM_CONTROL_BLOCK结构,则将当前的块全部分给当前块
current_mcb->is_available = 0;
return_pointer = (void *)((DWORD)current_mcb + sizeof(MEM_CONTROL_BLOCK));
// print_farmat_msg(" %d",current_mcb->current_blocksize - use_size);
if((current_mcb->current_blocksize - use_size) >sizeof(MEM_CONTROL_BLOCK))
{
// 4、当前量大于需要量大小满足申请量且分割后的空间能建立新的块,则分割剩余空间
other_mcb=(PMEM_CONTROL_BLOCK)((DWORD)current_mcb+use_size);
other_mcb->current_blocksize=current_mcb->current_blocksize-use_size;
// print_farmat_msg(" %d\n", other_mcb->current_blocksize);
other_mcb->is_available=1;
other_mcb->prior_block=current_mcb;
current_mcb->current_blocksize=dwBytes;
}
break;
}
}
nextblock:
//下一块
current_mcb=(PMEM_CONTROL_BLOCK)(sizeof(MEM_CONTROL_BLOCK)+current_mcb->current_blocksize+(DWORD)current_mcb);
}
//print_farmat_msg("mem %x,%d \n ",return_pointer,dwBytes);
return return_pointer;
}
BOOL mem_heap_free_block(HANDLE hHeap,DWORD dwFlags,LPVOID lpMem)
{
PMEM_CONTROL_BLOCK current_mcb,next_mcb,prior_mcb,Phead;
PMEM_CONTROL_BLOCK other_mcb = NULL;
print_farmat_msg(" free %x",lpMem);
current_mcb = lpMem-sizeof(MEM_CONTROL_BLOCK);
//重复释放、判决是否在堆的范围
if (current_mcb->is_available) return false;
current_mcb->is_available=1;
prior_mcb =current_mcb->prior_block;
next_mcb=lpMem+current_mcb->current_blocksize;
//当前是不是最后一块,判断技巧,下一块的内容位置<PHeapEndAddress(存在的比头部位置还小,) 则后面还有块
//且后块未分配 则合并
if((((DWORD)next_mcb+sizeof(MEM_CONTROL_BLOCK))<Phead->heap_end)&(next_mcb->is_available))
{
current_mcb->current_blocksize+=next_mcb->current_blocksize+sizeof(MEM_CONTROL_BLOCK);
}
// 当前是不是第一块,且前块未分配 则合并
if((current_mcb->prior_block!=hHeap)&(prior_mcb->is_available))
{
prior_mcb->current_blocksize+=current_mcb->current_blocksize+sizeof(MEM_CONTROL_BLOCK);
//后一块不是最后
if((DWORD)next_mcb+sizeof(MEM_CONTROL_BLOCK) < Phead->heap_end)
next_mcb->prior_block=current_mcb->prior_block;
}
return true;
}
void * kr_malloc(DWORD numbytes)
{
void *p=mem_heap_alloc(PHeapHeadAddress,0,numbytes);
//print_farmat_msg("kr_malloc: %d,%x \n ",numbytes,p);
return p;
}