contributed by < andy155224 >
一開始從 list.h
中發現了 LISTHEAD()
這個巨集,覺得可以透過這一個巨集來定義一個 new list 中的 head ,又因為要能夠回傳,所以寫成 static LISTHEAD()
,如下:
雖然這樣可以成功的創建一個 new list 的 head ,如下:
但是仔細思考過後我覺得這個作法的問題是一旦今天需要刪除 head,就會因為 head 是一個 static variable 而不是一個 pointer 導致沒有辦法將其 free 掉,所以我選擇改寫成正常宣告一個 list_head 這個結構的 pointer head
,然後透過 list.h
中的 INIT_LIST_HEAD()
來對 head
配置記憶體,如下:
想法是使用 list_for_each_entry_safe
來逐一走訪整個 queue 中的每一個 element,然後透過 container_of
來計算每一個 element 的記憶體起始位置,然後將其 free 掉。
但是我忽略了要 free 掉這一個 queue 中的頭 l
,所以會導致在做測試的時候會警告
而解決方法也很簡單,在上述程式碼的最後補上
後來在撰寫其他函式時,用 valgrind 檢查出了
我覺得
工程人員說話要精準,你可大膽列出你的推論,隨後證實。避免憑感覺。
是因為我在 q_free
中只把 element
都 free
掉,但是沒有把每一個 element
中的 member 的記憶體位置也一起 free
掉。必須要清乾淨,因為他們也是指標變數或是包含著指標變數的結構體。
仔細看 queue.h
中赫然發現有一個已經寫好的 function q_release_element
可以直接將整個結構體 element
所配置的記憶體空間,包含結構體內的其他結構體和指標變數所指向的記憶體都能一同 free 掉,所以就利用了這個 function 來改寫:
一開始寫出來的版本忘了配置記憶體空間給要 insert 的 node n
的 member value
,導致在做測試時會有錯誤跳出來
解決掉這個失誤的程式碼如下:
但又考慮到如果這行敘述成立
應該要將指到 NULL
的指標變數 free
掉,所以改寫成個別判斷
後來使用 valgrind 測試的時候發現也有 memory leak 的問題,仔細觀察後發現我額外宣告並配置了一個 list_head list
,這是沒有必要的,因為在宣告並配置 element_t n
時其 memeber 就包含了一個結構體 list_head ,改寫後就解決了 memory leak 的問題。
同時我也精簡了程式碼,因為不需要去 free 那些指向 NULL 的指標變數。
列出程式碼變更之處 (善用 diff
),不用張貼完整程式碼。
上述程式碼在 element_t *n
成功配置,但 char *value
配置失敗時,會導致配置成功的 element_t *n
之記憶體沒有被釋放。
應改為:
函式運作的邏輯和 q_insert_head
幾乎一樣,唯一的差別是將原先的
改成
但是這樣會發現這兩個函式的程式碼幾乎相同,所以可以將相同的部份提出來成為一個新的函式提供給 q_insert_head
和 q_insert_tail
使用,或是使用巨集來展開,這會是我在完成這份作業後可以優化 – 的地方。
這裡不是 optimize 的意思,僅為 improve,請查閱英英字典,理解二個詞彙的落差。
我想老師的意思是要慎用 優化 這個單詞,在這裡使用 改善 才能表達正確的意思。
strncpy
, snprintf
和 strlcpy
的差異。因為 strcpy
會存在潛在的 buffer overflow 的問題,所以應該用 strncpy
來限制寫入的位元組的大小。但是 strncpy
也並非是安全的,因為有可能會發生 dest
字串的結尾並沒有 null terminator 的問題,所以有了更安全的 strlcpy
能選擇。strlcpy
如果遇到寫入的位元組大小比 src
的位元組大小還要小的時候,會在欲寫入的位元組大小的最後一個位元填入 null terminator 。但是因為這需要安裝額外的 package 才能 include bsd/string.h
,所以我選擇使用 snprintf
來達到一樣的效果。
函式運作的邏輯和 q_remove_head
幾乎一樣,唯一的差別是將原先的
改成
同樣可以發現兩個函式的程式碼幾乎相同,所以改善程式碼的部份會列入我的 TODO List 中。
闡述接下來要怎麼修改程式碼,細節!
想法是透過一個型別為 list_head
的指標變數 tmp
和一個 會在 true 和 false 反覆震盪的 布林變數 flag
,在逐一走訪 queue
中的每一個 entry 時,每當 flag
為 true 時將 tmp
指向其下一個 entry 的 list。這樣當走訪完整個 queue
後 tmp
就會指向 queue
的第 個 entry,然後再將其刪除。
查閱教育部辭典「震盪」:震動擺盪,不安定
作為 bool
型態的變數,只能在 0 和 1 之間變化,而非「震盪」,注意用語。
但是這一段程式碼還有改善的空間。能改善的點在於
因為這一行敘述被翻譯成組合語言時會產生一次分支指令。而能避免產生分支指令的做法是透過一組快慢指標來達成相同的功能,這會列入我的 TODO List 中。