# 2023q1 Homework1 (lab0) contributed by < [s07362022](https://github.com/s07362022) > ## 開發環境 ```shell! $ gcc --version gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 $ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 2 On-line CPU(s) list: 0,1 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 2 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 140 Model name: 11th Gen Intel(R) Core(TM) i7-11370H @ 3.30GHz Stepping: 1 CPU MHz: 3302.402 BogoMIPS: 6604.80 Hypervisor vendor: VMware Virtualization type: full L1d cache: 48K L1i cache: 32K L2 cache: 1280K L3 cache: 12288K NUMA node0 CPU(s): 0,1 ``` ## 開發過程 ## q_new 和 q_free 實作 在 q_new() 創造新的queue時,先設定記憶體並且是否足夠,否則回傳 NULL 。 ```cpp! // q_new: 建立新的「空」佇列; struct list_head *q_new() { struct list_head *head = malloc(sizeof(struct list_head)); if(head){ INIT_LIST_HEAD(head);} return head; else{ return NULL; } } ``` 當你在遍歷一個鏈結串列時可能會遇到需要從串列中刪除當前遍歷的元素的情況。如果使用一般的迭代器巨集,如 list_for_each_entry,在刪除當前元素後繼續遍歷可能會導致未定義行為,因為你已經破壞了迭代器的內部狀態。list_for_each_entry_safe 通過在迭代之前就記錄下一個元素的位置來解決這個問題,從而使得在迭代過程中刪除元素變得安全。 element_t *entry, *safe;: 宣告兩個指標變數 entry 和 safe。entry 用於指向當前遍歷的元素,而 safe 用於儲存下一個元素的地址,這樣即使 entry 被刪除,遍歷也可以安全地繼續。這裡的 list 是 element_t 結構中用於鏈接到串列的成員的名稱。 free(l);: 最後,釋放鏈結串列的頭部所佔用的記憶體。 ```cpp= void q_free(struct list_head *l){ if(l){ return; } element_t *entry, *safe; list_for_each_entry_safe(entry,safe,l,list){ q_release_element(entry); } free(l); } ``` ## Insert an element at head of queue 使用 strdup 函式複製傳入的字串 s,並將複製後的字串地址賦值給新元素的 value 成員。strdup 函式同時進行分配記憶體和複製字串的操作。 如果字串複製(即記憶體分配)失敗,釋放之前為元素分配的記憶體,避免記憶體洩漏,然後返回 false。 ```cpp= bool q_insert_head(struct list_head *head, char *s){ if(!head){ return false; } element_t *node = malloc(sizeof(element_t)); if(!node){ return false; } node->value = strdup(s); if(!node->value){ free(node); return false; } list_add(&node,head); return true; } ``` ```cpp bool q_insert_tail(struct list_head *head, char *s) { if(!head){ return false;} element_t *noed = malloc(sizeof(element_t)); if(!node){ return false;} node->value = strdup(s); if(!node->value){ free(node); return false;} list_add_tail(&node->list,head); return true; } ```