现在的位置: 首页 > 综合 > 正文

malloc 的工作原理

2013年10月13日 ⁄ 综合 ⁄ 共 4912字 ⁄ 字号 评论关闭

阅读调试下面代码,将使你明白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

抱歉!评论已关闭.