▌第一次閱讀本系列的,可以先看:


▌第一次閱讀垃圾回收器系列,可以先看:


▌前文提要:

釋放標記分配這三個部分已經初步實現。
void free_all_register_address(void);               // 釋放
void register_address(void *address);               // 標記
void new_1d(void **ptr, int length, int type_side); // 分配
並且測試完成,成功運行。
不過這不是終點,因為程式使用了全域變數
所以今天來繼續完善,解決全域變數的部分。

▌全域變數的問題:

一般而言都不會建議過度使用全域變數
  • 第一,對變數命名造成困難。
  • 第二,變數的生命週期太長浪費記憶體空間
  • 第三,封裝性不好,無法預測哪裏改變了變數的值,
    • 也不能夠對輸入的值作檢測。
綜合以上,程式會難以維護
當然也有好處,
就是不用像下面這樣麻煩的寫...。

▌如何解決?

習慣是一個函數加上靜態變數去儲存數值,以代替全域變數。
函數限制變數視野範圍(scope),
靜態變數 可分配固定的記憶體空間。
正正是函數加上靜態變數的方法,請務必先了解當中的地址概念。(很重要
下面就不從頭說了,看不懂就 = w = 呵呵

▌解決全域變數的問題:

首先,創建一個儲存用的函數 connect_address_pool :
void connect_address_pool(void ****get_address_pool, void **get_index){

    /*用於儲存記憶體地址池的空間*/
 static void **address_pool = NULL;
 static int index = 0;  //address_pool 的索引

 *get_address_pool = &address_pool;
 *get_index = &index;
}
有兩個靜態變數: address_pool 和 index 。
由於 address_pool 是二維的,
輸入一個三維指標的地址,去取得二維指標的地址,返回調用它的程式,
使調用它的程式可以操作 address_pool 。
下面是實際應用在釋放標記分配這三個部分的情況:

▌釋放的部分:

void free_all_register_address(void) {

    /*用於取得記憶體地址池的資料*/
 void ***address_pool = NULL;
 int *index;

 /*取得記憶體地址池的資料*/
 connect_address_pool(&address_pool, &index);
    
 /*遍歷 address_pool 的空間*/
 for (int i = 0; i < *index; i++) {
  free((*address_pool)[i]);  //釋放曾經記錄過的記憶體地址的空間
  (*address_pool)[i] = NULL;
 }

    /*釋放用於紀錄的空間*/
 free(*address_pool);
 *address_pool = NULL;
}

▌標記的部分:

void register_address(void *address){
    
    /*用於取得記憶體地址池的資料*/
 void ***address_pool = NULL;
 int *index;

 /*取得記憶體地址池的資料*/
 connect_address_pool(&address_pool, &index);
    
    /*擴大、重新分配用於儲存記憶體地址的空間*/
    void **temp_ptr = NULL;  //中轉指標
 temp_ptr = (void**)realloc(*address_pool, (*index + 1) * sizeof(void*));
    
    /*對realloc分配記憶體的錯誤檢測*/ // ...省略......
    
    /*成功建立的空間分配給address_pool*/
 *address_pool = temp_ptr;  //取得中轉指標的地址
    
    /*註冊記憶體地址*/
 (*address_pool)[*index] = address;
 (*index)++;  //空間擴大、索引移位
    
}

▌分配的部分:

分配的部分不包含操作 address_poolindex 的部分,
所以沒有分別喔。

▌現在加入 connect_address_pool 函數後,只要利用:

/*用於取得記憶體地址池的資料*/
void ***address_pool = NULL;
int *index;

/*取得記憶體地址池的資料*/
connect_address_pool(&address_pool, &index);
程式的 *address_pool 和 *index ,
就會等價靜態變數 address_pool 和 index 。
令程式連接了/可以操作 address_pool 和 index 。

▌目前我習慣解決全域變數的問題的方法就醬~


▌封裝性不夠,還可以加強,繼續完善。