天天看點

malloc 的工作原理

閱讀調試下面代碼,将使你明白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;

}

繼續閱讀