【 聲明:著作權,歡迎轉載,請勿用於商業用途。 聯絡信箱:feixiaoxing @163.com】
連結節點的記憶體配置方法,其實就是一種按需分配的記憶體配置方法。簡單一點說,就是你需要多少記憶體,我就給你多少記憶體。當然,為了把分配的記憶體都連起來,我們還需要對分配節點進行管理記錄。就比如下面這個資料結構,
typedef struct _MNG_NODE{ struct _MNG_NODE* next; unsigned int size;}MNG_NODE;
其中,next節點記錄了下面一個節點的位置,size表示了當前節點下方的記憶體大小。在記憶體初始化的時候,我們預設起始記憶體塊就是一個大節點,其中前面8個位元組就是上面的內容。此時,如果需要進行記憶體拆分,我們就可以把一個節點拆分成兩個節點,就比如這樣,
pNew = (MNG_NODE*)((char*)pOld + sizeof(MNG_NODE) + pOld->size - (sizeof(MNG_NODE) + size));
pNew代表了新產生的結點,pOld代表了原來的節點。為了不影響原來的節點,每次分配新節點的時候必須在記憶體的高端位置進行分配。這樣也保證了原來節點結構和資料的連貫性。當然分配結束之後,只需要對節點的的size重新進行一下賦值就可以了。
pNew->size = size; pOld->size -= sizeof(MNG_NODE) + size;
此時pOld節點會歸還到pFreeList當中,而產生的pNew節點則插入到pAllocList當中。其中,pFreeList表示當前的空閑節點,pAllocList表示已指派節點。相比較而言,記憶體的釋放就比較簡單,只需要把節點找出來插入到pAllocList中即可。當然,此時如果能做一下前後節點的合并工作就更好了。
不過,上面描述的步驟只是就比較重要知識點講解了一下。在真正設計代碼的過程中還需要考慮到節點的尋找、記憶體大小的判斷、資料初始化、鏈表插入、測試案例編寫等工作,步驟會稍微繁瑣一下。下面我們就給出完整的程式碼範例。
/************************************************** malloc & free in link node algorithm**************************************************/#include <string.h>#include <malloc.h>/************************************************** struct definition**************************************************/typedef struct _MNG_NODE{ struct _MNG_NODE* next; unsigned int size;}MNG_NODE;/************************************************** global variable declaration**************************************************/#define MEM_BUFFER_LENGTH (0x1 << 24)static void* pGlbData;static MNG_NODE* pFreeList;static MNG_NODE* pAllocList;/************************************************** function: add node into headlist**************************************************/static void add_node_into_list_head(MNG_NODE* pNode, MNG_NODE** ppList){ pNode->next = *ppList; *ppList = pNode; }/************************************************** function: find best fit node**************************************************/static MNG_NODE* find_best_fit_node(unsigned int size){ MNG_NODE* pCur = pFreeList; MNG_NODE* pPre = pCur; while(pCur && pCur->size < (size + sizeof(MNG_NODE))) { pPre = pCur; pCur = pCur->next; } if(NULL == pCur) return NULL; if(pFreeList == pCur) pFreeList = pFreeList->next; else pPre->next = pCur->next; return pCur;}/************************************************** function: implement memory allocation**************************************************/static void* _mem_malloc(unsigned int size){ MNG_NODE* pOld; MNG_NODE* pNew; pOld = find_best_fit_node(size); if(NULL == pOld) return NULL; pNew = (MNG_NODE*)((char*)pOld + sizeof(MNG_NODE) + pOld->size - (sizeof(MNG_NODE) + size)); pNew->size = size; pOld->size -= sizeof(MNG_NODE) + size; add_node_into_list_head(pOld, &pFreeList); add_node_into_list_head(pNew, &pAllocList); return (void*)((char*)pNew + sizeof(MNG_NODE));}/************************************************** function: memory allocation**************************************************/void* mem_malloc(unsigned int size){ if(0 == size) return NULL; if(size > (MEM_BUFFER_LENGTH - sizeof(MNG_NODE))) return NULL; return _mem_malloc(size);}/************************************************** function: find previous node **************************************************/static MNG_NODE* find_previous_node(MNG_NODE* pNode){ MNG_NODE* pFind = pAllocList; MNG_NODE* pPre = NULL; while(pFind && pFind != pNode) { pPre = pFind; pFind = pFind->next; } if(NULL == pFind) return NULL; return pPre;}/************************************************** function: implement memory free**************************************************/static void _mem_free(MNG_NODE* pNode){ MNG_NODE* pPreNode; if(pNode == pAllocList) { pAllocList = pAllocList->next; add_node_into_list_head(pNode, &pFreeList); return; } pPreNode = find_previous_node(pNode); if(NULL == pPreNode) return; pPreNode->next = pNode->next; add_node_into_list_head(pNode, &pFreeList); return;}/************************************************** function: free memory function**************************************************/void mem_free(void* pData){ if(NULL == pData) return; if(pData < pGlbData || pData >= (void*)((char*)pGlbData + MEM_BUFFER_LENGTH)) return; _mem_free(pData - sizeof(MNG_NODE));}/************************************************** function: get memory buffer**************************************************/void mem_init(){ pGlbData = (void*)malloc(MEM_BUFFER_LENGTH); if(NULL == pGlbData) return; memset(pGlbData, 0, MEM_BUFFER_LENGTH); pFreeList = (MNG_NODE*)pGlbData; pFreeList->size = MEM_BUFFER_LENGTH - sizeof(MNG_NODE); pAllocList = NULL;}/************************************************** function: free memory buffer**************************************************/void mem_exit(){ if(NULL != pGlbData) free(pGlbData); pFreeList = NULL; pAllocList = NULL;}/************************************************** function: file starts here**************************************************/int main(int argc, char* argv[]){ mem_init(); mem_exit(); return 1;}