1. 程式人生 > 實用技巧 >再也不怕分配記憶體了

再也不怕分配記憶體了

最近改使用者組管理專案bug時,遇到一個關於記憶體分配的問題。原來是同事用一個長度為4096的字元陣列分配記憶體,
strncpy()函式造成拷貝錯誤,導致使用者組管理編輯、新增和刪除功能不可用。
雖然是個小問題,但是記憶體分配一直都是很重要的,嚴重時會導致系統崩潰。

一、記憶體分配方式

靜態儲存區域中分配(系統分配,如全域性變數、static變數)
棧中進行分配(系統分配,如字元陣列)
堆中進行分配(使用者動態分配,涉及malloc、calloc、realloc、free函式)

二、常見錯誤及解決方案

  1. 使用未分配的記憶體
    • 使用記憶體之前檢查指標是否為NULL
  2. 賦予初值,即便是賦予零值也不可省略;
    • 使用了分配成功但是未初始化的記憶體,導致野指標;
  3. 記憶體分配且初始化了,但是進行了越界操作
    • 注意下表的使用不能超出邊界
  4. 忘記釋放記憶體造成記憶體洩漏;
    • 申請記憶體的方式和釋放記憶體的方式需要成雙成對
  5. free後,未將指標置為NULL,導致也野指標;
    • 使用free記憶體之後,把指標置為NULL

1. 專案問題

專案中的記憶體分配方式就是棧分配,靜態分配,當輸入的變數長度超過字元陣列最大長度時,記憶體越界。

static int deleteRedUsr(int groupID, char *users, long long eventID)
{
    /* some code */

    char usrs[4096] = {0};  //當strlen(users) > 4094則會記憶體越界
    strncpy(usrs, users, strlen(users)); 

    /* some code */
}

2. 專案解決方案

不推薦擴大字元陣列,而應該使用動態分配記憶體

/* 
 * 釋放記憶體,並將指標置為NULL
 * 最好在工具標頭檔案,重複使用
 */
#define FREE(a)       if( a!= NULL ){ free(a); a=NULL; }

static int deleteRedUsr(int groupID, char *users, long long eventID)
{
    /* some code */

    char *usrs = NULL;
    usrs = (char *)malloc(strlen(users) + 1); //動態分配記憶體
    strcpy(usrs, users);

    /* some code */

    FREE(usrs); //在每個return前,釋放記憶體,避免記憶體洩漏

    /* some code */
}