釋放、標記、分配這三個部分已經初步實現。
void free_all_register_address(void); // 釋放
void register_address(void *address); // 標記
void new_1d(void **ptr, int length, int type_side); // 分配
並且測試完成,成功運行。
不過這不是終點,因為程式使用了全域變數,
所以今天來繼續完善,解決全域變數的部分。
一般而言都不會建議過度使用全域變數,
綜合以上,程式會難以維護。
當然也有好處,
就是不用像下面這樣麻煩的寫...。
我習慣是一個函數加上靜態變數去儲存數值,以代替全域變數。
函數限制變數視野範圍(scope),
靜態變數 可分配固定的記憶體空間。
在這裏請大家回去看 Days 4: 重溫指標:靜態變數的地址、函數回傳地址
至 Days 6: 重溫指標:不使用回傳地址方式的函數(續.)。
正正是函數加上靜態變數的方法,請務必先了解當中的地址概念。(很重要
下面就不從頭說了,看不懂就 = 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_pool
, index
的部分,
所以沒有分別喔。
connect_address_pool
函數後,只要利用:/*用於取得記憶體地址池的資料*/
void ***address_pool = NULL;
int *index;
/*取得記憶體地址池的資料*/
connect_address_pool(&address_pool, &index);
程式的 *address_pool
和 *index
,
就會等價靜態變數 address_pool
和 index
。
令程式連接了/可以操作 address_pool
和 index
。