malloc的实现模拟

本文深入解析了malloc函数的工作原理,包括内存分配与回收的过程。通过模拟实现,详细介绍了内存控制块的概念及其如何帮助查找和标记可用内存区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/*
该函数演示了malloc 的工作原理:
1. malloc 在一块平台的内存区管理内存(可以称之为堆)
2. malloc 由管理块和数据块构成
3. malloc 首先以链表的方式搜索已管理的内存,没有找到,再从大池里扩展一块进入valid_address 管理区
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <stdafx.h>
#include <malloc.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);

/********* func define **********/
void simu_init(void)
{
    g_last_valid_address = malloc(SIZE);
}

//========================================================================//
int malloc_test(void)
{
    char *p = 0;

    p = (char *)malloc(100000);
    if(p)
    {
        printf("malloc sucd!!! the start addr is: %d/r/n", (int)p);
    }
    else
    {
        printf("malloc failed!!! the start addr is: %d/r/n", (int)p);
    }
    free(p);
    p = 0;
    return 0;
}

//========================================================================//
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;

    //malloc_test();
    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 = (mem_control_block *)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;
}

 

注意:转贴

看完之后就知道为什么使用malloc会产生很多内存碎片了,不知道也没有不产生碎片的方式

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值