閱讀調試下面代碼,将使你明白malloc 的工作原理
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define SIZE 0x10000
struct mem_control_block
{
int is_available;
int size;
};
int has_initialized = 0;
void *g_managed_memory_start;
void *g_last_valid_address;
void malloc_init();
void myfree(void *firstbyte);
void *mymalloc(long numbytes);
void simu_init(void)
{
g_last_valid_address=malloc(SIZE);
}
void sbrk(int n)
{
// 另外,若是真實的系統配置設定,此處是将零散的小記憶體合并為平坦的大記憶體的好位置。這裡模拟就不用考慮了。
if(((int)g_last_valid_address+n)>(int)g_managed_memory_start+SIZE)
{
printf("memory full!/n");
exit(1);
}
}
// 測試程式
int main(void)
{
void *p1, *p2, *p3,*p4,*p5;
simu_init();
p1=mymalloc(0x100);
p2=mymalloc(0x200);
p3=mymalloc(0x300);
printf("p1 offset: %x/n",(char *)p1-(char *)g_managed_memory_start);
printf("p2 offset: %x/n",(char *)p2-(char *)g_managed_memory_start);
printf("p3 offset: %x/n",(char *)p3-(char *)g_managed_memory_start);
myfree(p2);
p4=mymalloc(0x50);
p5=mymalloc(0x50);
printf("p4 offset: %x/n",(char *)p4-(char *)g_managed_memory_start);
printf("p5 offset: %x/n",(char *)p5-(char *)g_managed_memory_start);
myfree(p1);
myfree(p3);
myfree(p4);
myfree(p5);
system("pause");
return 0;
}
// 僅執行一次, 為g_managed_memory_start 付初值
void malloc_init()
{
// g_last_valid_address = sbrk(0);
g_managed_memory_start = g_last_valid_address;
has_initialized = 1;
}
// 将mcb 的标志置位即可
void myfree(void *firstbyte)
{
struct mem_control_block *mcb;
mcb = (struct mem_control_block*)((int)firstbyte - sizeof(struct mem_control_block));
mcb->is_available = 1;
return;
}
void *mymalloc(long numbytes)
{
void *current_location;
struct mem_control_block *current_location_mcb;
void *memory_location;
if(! has_initialized) {
malloc_init();
}
numbytes = numbytes + sizeof(struct mem_control_block);
memory_location = 0;
current_location = g_managed_memory_start;//the start is fixed
while(current_location != g_last_valid_address)
{
current_location_mcb =
(struct mem_control_block *)current_location;
if(current_location_mcb->is_available)
{
if(current_location_mcb->size >= numbytes)
{
current_location_mcb->is_available = 0;
memory_location = current_location;
break;
}
}
current_location = (char *)current_location + //look through the chain
current_location_mcb->size;
}
if(! memory_location)
{
sbrk(numbytes);
memory_location = g_last_valid_address;
g_last_valid_address = (char *)g_last_valid_address + numbytes; //adjust g_last_valid_address
current_location_mcb = memory_location;
current_location_mcb->is_available = 0;
current_location_mcb->size = numbytes;
}
memory_location = (char *)memory_location + sizeof(struct mem_control_block);
return memory_location;
}