内存管理

  你是否好奇过Malloc和Free内部是如何实现?本文为你揭秘。

  动态内存管理分为定长内存管理和变成内存管理。定长内存管理每次都分配固定长度内存,算法复杂度是O(1);变长内存管理是申请多少字节就分配多少直接,算法复杂度是O(n)。为了追求时间和空间的平衡,因此本文综合使用定长和变长内存管理。

定长内存管理

void InitFMemory(unsigned char *mem, unsigned int size)
{
    int             num = 0;
    int             i = 0;
    FMemNode         *current = NULL;
    FMemNode         *next = NULL;
    
    num = size / (sizeof(FMemNode) + F_MEMORY_LENGTH);
    
    gFMemList.listHead = (FMemNode *)mem;
    gFMemList.nodeBase = mem;
    gFMemList.memBase = mem + num * sizeof(FMemNode);
    gFMemList.num = num;

    for(i = 0; i < num - 1; i++)
    {
        current = (FMemNode *)(gFMemList.nodeBase + (sizeof(FMemNode) * i));
        next = (FMemNode *)(gFMemList.nodeBase + (sizeof(FMemNode) * (i + 1)));
        current->next = next;
    }

    ((FMemNode *)(gFMemList.nodeBase + (sizeof(FMemNode) * i)))->next = NULL;
    
    return;
}

unsigned char* FMalloc()
{
    unsigned char     *ret = NULL;
    unsigned int     index = 0;
    FMemNode         *pos = NULL;
    
    if(NULL != gFMemList.listHead)
    {
        pos = gFMemList.listHead;
        gFMemList.listHead = pos->next;
        
        index = ((unsigned char *)pos - (unsigned char *)(gFMemList.nodeBase)) / sizeof(FMemNode);
        ret = (unsigned char *)(gFMemList.memBase) + index * F_MEMORY_LENGTH;
        pos->next = (FMemNode *)ret;
    }
    
    return ret;
}

int FFree(unsigned char *mem)
{
    unsigned int     index = 0;
    FMemNode         *pos = NULL;
    
    index = (mem - gFMemList.memBase) / F_MEMORY_LENGTH;
    pos = (FMemNode *)(gFMemList.nodeBase + index * sizeof(FMemNode));
    if(mem == (unsigned char *)(pos->next))
    {
        pos->next = gFMemList.listHead;
        gFMemList.listHead = pos;
        return 0;
    }
    
    return 1;
}

void ShowFMemInfo()
{
    FMemNode         *pos = gFMemList.listHead;
    unsigned int    freeNum = 0;
    
    while(NULL != pos)
    {
        freeNum++;
        pos = pos->next;
    }
    
    printf("Fix Memory info:\n");
    printf("totoal = %d, free = %d\n", gFMemList.num, freeNum);
}

变成内存管理

void InitVmemory(unsigned char *mem, unsigned int size)
{
    VMemNode        *pNode = NULL;
    
    init_list_head(&gVMemList);
    
    pNode = (VMemNode *)mem;
    pNode->freeSize = size;
    pNode->UsedSize = 0;
    pNode->mem = mem + sizeof(VMemNode);
    init_list_head(&pNode->list);
    
    list_add_tail(&pNode->list, &gVMemList);
}
unsigned char* VMalloc(unsigned int size)
{
    unsigned char     *ret = NULL;
    List            *pos = NULL;
    VMemNode        *pNode = NULL;
    VMemNode        *pNewNode = NULL;
    
    list_for_each(pos, &gVMemList)
    {
        pNode = (VMemNode *)pos;
        if(pNode->freeSize >= (size + sizeof(VMemNode)))
        {
            pNewNode = (VMemNode *)(pNode->mem + pNode->freeSize + pNode->UsedSize - (size + sizeof(VMemNode)));
            pNewNode->freeSize = 0;
            pNewNode->UsedSize = size;
            pNewNode->mem = (unsigned char*)(pNewNode + 1);
            init_list_head(&pNewNode->list);
            list_add_tail(&pNewNode->list, pNode->list.next);
            
            pNode->freeSize = pNode->freeSize - (size + sizeof(VMemNode));
            
            ret = pNewNode->mem;
            
            break;
        }
    }
    
    return ret;
}

void VFree(unsigned char *mem)
{
    List            *pos = NULL;
    VMemNode        *pNode = NULL;
    VMemNode        *pPreNode = NULL;
    
    list_for_each(pos, &gVMemList)
    {
        pNode = (VMemNode *)pos;
        if(pNode->mem == mem)
        {
            pPreNode = (VMemNode *)(pos->prev);
            pPreNode->freeSize = pPreNode->freeSize + pNode->freeSize + pNode->UsedSize + sizeof(VMemNode);
            list_del(&pNode->list);
            break;
        }
    }
    
    return;
}

void ShowVMemInfo()
{
    List            *pos = NULL;
    VMemNode        *pNode = NULL;
    unsigned int    num = 0;
    
    printf("Var Memory info:\n");
    list_for_each(pos, &gVMemList)
    {
        pNode = (VMemNode *)pos;
        num++;
        printf("num = %d, ptr = 0x%x, freeSize = %d, usedSize = %d\n", num, pNode->mem, pNode->freeSize, pNode->UsedSize);
    }
    
    return;
}

二者综合使用

void InitMemory(unsigned char *mem, unsigned int size)
{
    unsigned char *fmem = NULL;
    unsigned char *vmem = NULL;
    unsigned int  fsize = 0;
    unsigned int  vsize = 0;
    
    fsize = size / 2;
    vsize = size - fsize;
    
    fmem = mem;
    vmem = mem + fsize;
    
    InitFMemory(fmem, fsize);
    InitVmemory(vmem, vsize);
    
    return;
}

unsigned char* Malloc(unsigned int size)
{
    unsigned char *mem = NULL;
    
    if(size <= F_MEMORY_LENGTH)
    {
        mem = FMalloc();
    }
    
    if(NULL == mem)
    {
        mem = VMalloc(size);
    }
    
    return mem;
}

void Free(unsigned char *mem)
{
    if(FFree(mem))
    {
        VFree(mem);
    }
    
    return;
}

void ShowMemInfo()
{
    printf("-----------Memory Info-----------\n");
    ShowFMemInfo();
    ShowVMemInfo();
}

测试代码

#include <stdio.h>
#include "memory.h"

int main()
{
    unsigned char data[1024 * 1024] = {0};
    
    InitMemory(data, sizeof(data));
    
    unsigned char *p1 = Malloc(20);
    unsigned char *p2 = Malloc(200);
    unsigned char *p3 = Malloc(16);
    
    ShowMemInfo();
    
    Free(p1);
    Free(p2);
    Free(p3);
    
    ShowMemInfo();
    
    return 0;
}
原文地址:https://www.cnblogs.com/chusiyong/p/15719455.html