阅读调试下面代码,将使你明白malloc 的工作原理
/*
整理: hjjdebug
time: 2009/4
该函数演示了malloc 的工作原理:
1. malloc 在一块平台的内存区管理内存(可以称之为堆)
2. malloc 由管理块和数据块构成
3. malloc 首先以链表的方式搜索已管理的内存,没有找到,再从大池里扩展一块进入valid_address 管理区
*/
#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;
}
void malloc_init()
{
/* grab the last valid address from the OS */
// g_last_valid_address = sbrk(0);
/* we don't have any memory to manage yet, so
*just set the beginning to be g_last_valid_address
*/
g_managed_memory_start = g_last_valid_address;
/* Okay, we're initialized and ready to go */
has_initialized = 1;
}
void myfree(void *firstbyte)
{
struct mem_control_block *mcb;
/* Backup from the given pointer to find the
* mem_control_block
*/
mcb = (struct mem_control_block*)((int)firstbyte - sizeof(struct mem_control_block));
/* Mark the block as being available */
mcb->is_available = 1;
/* That's It! We're done. */
return;
}
void *mymalloc(long numbytes)
{
/* Holds where we are looking in memory */
void *current_location;
/* This is the same as current_location, but cast to a
* memory_control_block
*/
struct mem_control_block *current_location_mcb;
/* This is the memory location we will return. It will
* be set to 0 until we find something suitable
*/
void *memory_location;
/* Initialize if we haven't already done so */
if(! has_initialized) {
malloc_init();
}
/* The memory we search for has to include the memory
* control block, but the users of malloc don't need
* to know this, so we'll just add it in for them.
*/
numbytes = numbytes + sizeof(struct mem_control_block);
/* Set memory_location to 0 until we find a suitable
* location
*/
memory_location = 0;
/* Begin searching at the start of managed memory */
current_location = g_managed_memory_start;//the start is fixed
/* Keep going until we have searched all allocated space */
while(current_location != g_last_valid_address)
{
/* current_location and current_location_mcb point
* to the same address. However, current_location_mcb
* is of the correct type, so we can use it as a struct.
* current_location is a void pointer so we can use it
* to calculate addresses.
*/
current_location_mcb =
(struct mem_control_block *)current_location;
if(current_location_mcb->is_available)
{
if(current_location_mcb->size >= numbytes)
{
/* Woohoo! We've found an open,
* appropriately-size location.
*/
/* It is no longer available */
current_location_mcb->is_available = 0;
/* We own it */
memory_location = current_location;
/* Leave the loop */
break;
}
}
/* If we made it here, it's because the Current memory
* block not suitable; move to the next one
*/
current_location = (char *)current_location + //look through the chain
current_location_mcb->size;
}
/* If we still don't have a valid location, we'll
* have to ask the operating system for more memory
*/
if(! memory_location)
{
/* Move the program break numbytes further */
sbrk(numbytes);
/* The new memory will be where the last valid
* address left off
*/
memory_location = g_last_valid_address;
/* We'll move the last valid address forward
* numbytes
*/
g_last_valid_address = (char *)g_last_valid_address + numbytes; //adjust g_last_valid_address
/* We need to initialize the mem_control_block */
current_location_mcb = memory_location;
current_location_mcb->is_available = 0;
current_location_mcb->size = numbytes;
}
/* Now, no matter what (well, except for error conditions),
* memory_location has the address of the memory, including
* the mem_control_block
*/
/* Move the pointer past the mem_control_block */
memory_location = (char *)memory_location + sizeof(struct mem_control_block);
/* Return the pointer */
return memory_location;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hejinjing_tom_com/archive/2009/04/09/4059711.aspx