# 2023q1 Homework1 (lab0)
contributed by <[`Otuslettia`](https://github.com/Otuslettia)>
## 開發環境
```
$ gcc --version
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
```
> 此處參考[hongpei100](https://hackmd.io/@MrShark/S1Z73ZTTj#%E5%AF%A6%E9%A9%97%E7%92%B0%E5%A2%83)的文章中,老師關於 `lscpu` 套件的回覆,先執行 `$export LC_ALL=C`
```
$export LC_ALL=C
$lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Address sizes: 39 bits physical, 48 bits virtual
Byte Order: Little Endian
CPU(s): 12
On-line CPU(s) list: 0-11
Vendor ID: GenuineIntel
Model name: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
CPU family: 6
Model: 165
Thread(s) per core: 2
Core(s) per socket: 6
Socket(s): 1
Stepping: 2
CPU max MHz: 5000.0000
CPU min MHz: 800.0000
BogoMIPS: 5199.98
```
## 開發過程
### queue.c
#### `q_new()`
首先用 `malloc` 配置記憶體,當 allocation fail 時回傳 `NULL`,通過 `INIT_LIST_HEAD()` 將 `list->next` 及 `list->head` 指回 `list`。
```
struct list_head *q_new()
{
struct list_head *new = malloc(sizeof(struct list_head));
if (!new)
return NULL;
INIT_LIST_HEAD(new);
return new;
}
```
#### `q_free()`
用`list_for_each_entry_safe` 走訪每一個元素,然後依序釋放記憶體。
```
/* Free all storage used by queue */
void q_free(struct list_head *l)
{
element_t *entry, *safe;
list_for_each_entry_safe (entry, safe, l, list) {
q_release_element(entry);
}
free(l);
}
```
#### `q_insert_head()` / `q_insert_tail`
`q_insert_head()` 及 `q_insert_tail()` 有重複 `malloc` `element_t` 行為 [e2e4af4](e2e4af4127db09baa668c9f7615608051c949018)。
`[!] You are not allowed to change the header file queue.h or list.h` ,將重複部份寫成函式放在 `queue.c` 裡面。
* 若 `strdup()` `malloc fail`,要記得釋放已配置的記憶體,否則有 `memory leak` 問題。
* 避免 `element_new_char()` 回傳指標和 `head` 一起判斷,否則 `head` 為 `NULL` 時,須對新建 `element_t` 執行 `free()` 。
```
element_t *element_new_char(char *s)
{
if (!s)
return NULL;
element_t *s_new = malloc(sizeof(struct list_head));
if (!s_new)
return NULL;
s_new->value = strdup(s);
if (!s_new->value) {
free(s_new);
return NULL;
}
return s_new;
}
```
#### `q_remove_head()`
當 `sp` 為 `NULL` 時,應直接 `remove` ,不複製 `value` 進 `sp` ,起初誤以為 `sp` / `head` 其一為 `NULL` 時就回傳 `NULL` [364819c](364819c718c2875ba4c9bca6cb76fa019a5f49aa)。
* `list_del()` 會處理 `list_head` 內容的指標更改,不會進行 `free()` 。
```
/* Remove an element from head of queue */
element_t *q_remove_head(struct list_head *head, char *sp, size_t bufsize)
{
if (!list_empty(head))
return NULL;
element_t *toRem = list_first_entry(head, element_t, list);
if (sp) {
memset(sp, '\0', bufsize);
strncpy(sp, toRem->value, bufsize - 1);
}
list_del(&toRem->list);
return toRem;
}
```