C語言內存管理(內存池)


C語言可以使用alloc從棧上動態分配內存。

 

內存碎片

Malloc/free或者new/delete大量使用會造成內存碎片,這種碎片形成的機理如下:

內存碎片一般是由於空閑的內存空間比要連續申請的空間小,導致這些小內存塊不能被充分的利用,舉個例子:

如果有100個單位的連續空閑內存,那么先申請3單元的連續內存,再申請50單元的內存,這時釋放一開始的3單元的內存。這時,如果你一直申請比三單元大的內存單元,那么開始的那連續的三單元就一直不能被使用。

 

一個簡單的內存池的寫法:

struct memblock
{
   int              used;
   void*            data;
   struct memblock* next;
   struct memblock* createnext;
};

 

struct mempool
{
    int            size;//memblock大小
    int            unused;//空閑的memblock大小
    int            datasize;//每次分配的數據大小(就是memblock.data)
    struct memblock*    free_linkhead;//空閑memblock鏈表頭
    struct memblock*    create_linkhead;//所有創建的memblock鏈表頭,內存池釋放的時候使用,防止內存池釋放的似乎還有memblock未歸還的情況
    
};
typedef void (*free_callback)(void*);//釋放回調函數,釋放membloc.data用,可以簡單的直接用free函數

void    mempool_init(int initialSize,int datasize);//初始化mempool
void    mempool_dealloc(struct mempool* pool,free_callback callback);//釋放mempool
void*    mempool_get(struct mempool* pool);//獲取一個memblock
void    mempool_release(struct mempool* pool,struct memblock* block);//歸還一個memblock

/*********************************
 * mempool
 * ******************************/
//malloc一個memblock
static struct memblock* mempool_allocblock( struct mempool* pool );

//------------------implement--------
void*
mempool_init( int initialSize, int datasize )
{
    struct mempool* pool = malloc( sizeofstruct mempool ) );
    pool->unused = 0;
    pool->datasize = datasize;
    pool->free_linkhead = NULL;
  
    //預先初始化initialSize個內存塊
     pool->create_linkhead = NULL;
    int i;
    for ( i = 0; i < initialSize; i++ ) {
        struct memblock* block = mempool_allocblock( pool );
        mempool_release( pool, block );
    }
    return ( pool );
}

void
mempool_dealloc( struct mempool* pool, free_callback callback )
{
    struct memblock* block = NULL;
    //將所有創建的memblock釋放了
    while ( pool->create_linkhead != NULL ) {
        block = pool->create_linkhead;
        pool->create_linkhead = pool->create_linkhead->createnext;
    //執行free回調。
        if ( callback ) {
            ( *callback )( block->data );
        }
        free( block );
    }
    free( pool );
    L_DEBUG( "%s:size(%d),unused(%d)", __func__, pool->size, pool->unused );
}

static struct memblock*
mempool_allocblock( struct mempool* pool )
{
    struct memblock* block = malloc( sizeofstruct memblock ) );
    block->data = malloc( sizeof( pool->datasize ) );
    block->next = NULL;
    block->used = 1;//表示已使用

    //加入所有創建的memblock的鏈表頭
    block->createnext = pool->create_linkhead;
    pool->create_linkhead = block;

    pool->size++;
    return ( block );
}

void
mempool_release( struct mempool* pool, struct memblock* block )
{
    if ( block == NULL ) {
        L_WARN( "%s:release a NULL!", __func__ );
        return;
    }
    if ( block->used != 1 ) {
        L_WARN( "%s:used!=1", __func__ );
        return;
    }
    //將歸還的內存塊放到空閑鏈表頭。
    block->used = 0;//表示空閑
    block->next = pool->free_linkhead;
    pool->free_linkhead = block;
    pool->unused++;//空閑數+1
}

void*
mempool_get( struct mempool* pool )
{
   
    struct memblock* block = NULL;
    if ( pool->free_linkhead ) {
    //從空閑鏈表頭取出一個內存塊
        block = pool->free_linkhead;
        pool->free_linkhead = pool->free_linkhead->next;
        block->next = NULL;
        block->used = 1;//表示已使用
        pool->unused--;//空閑內存塊數-1
    }
    else {
    //沒有空閑的內存塊,創建一個
        block = mempool_allocblock( pool );
    }
    return ( block );
}

 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM