contributed by < butastur-rtos
>
Overview
] union 的 size 取決於 member 裡 size 最大的 member
是一個 notation,表示執行的時間是一個常數,不會因為輸入的資料大小而執行的時間有所不同。
因為要在 的時間內執行完成 q_insert_tail, 所以在 list 裡一個一個往下找 tail 的作法是不可能的。 page 4 的圖有一個 head 的additional fields, 應該可以在每一次的 q_insert_tail 紀錄 list 裡最後一個 node 的 address, 所以初步的想法是從 head 的 additional fields 開始著手
[queue.h]
果然,註解有這麼一段話… add more fields…
中英文字間記得空白
課程助教
commit 試一下
So, use git add
like:
再 commit 試試
第4行輸入 e,可以編輯 message
第7行輸入 y,因為 y 不是有效選項, 所以出現 help
第17行輸入 e, 再次編輯 message, 因為 message 有限制標題開頭要大寫
commit 還是失敗, 所以依照 git 的提示再試一下
git config –global –edit
git commit –amend –reset-author
commit 之前修改一下 message
看起來, 應該要執行 git push
才對
將 git repository 的 https 改為 ssh,並且設定好 ssh-key,之後 git push 就不需要輸入帳號密碼
參照 更換遠端伺服器倉庫網址
int q_size(queue_t *q)
由於要在 的常數時間內執行完成, 所以也不可能每次都遍歷整個 list 來取得 queue 的大小,
queue.h
的註解有寫You will need to add more fields to this structure to efficiently implement q_size and q_insert_tail
所以, 增加 int size 到typedef struct queue_t
接下來修改 q_size 的傳回值, 改成傳回q->size
格式不對, 所以 commit 失敗
依 git 指示執行 clang-format
後再重新 git add
, 然後再 git commit
, git push
Remove one element, so the size should decrease, 第6行把size減一
應該先用 qtest
測試過
避免用 git commit -m
,設定好 $EDITOR 環境變數,用你偏好的編輯器寫好 git commit messages
q_insert_head的parameter q如果是NULL, 要傳回false
initialize a new queue, if malloc return NULL q_new return NULL
q_remove_head須要Return false if queue is NULL or empty
是不是 prev->value 也要 free?
這點我也很好奇,但我在釋放
prev
的記憶體空間前先釋放prev->value
的記憶體空間卻出現以下錯誤訊息:LawrenceSun, Sep 23, 2018 3:56 PM
我也是碰到一樣的 ERROR, 因為 prev->value 是透過 strdup 取得 a pointer to a new string, 原本好奇會不會是因為這樣所以不能 free, 於是查了一下 man, 查到這一段
The strdup() function returns a pointer to a new string which is a
duplicate of the string s. Memory for the new string is obtained with
malloc(3), and can be freed with free(3).
所以我還需要再研究一下要不要 free(prev->value)
butastur-rtosSun, Sep 23, 2018 5:31 PM
是 strdup 惹的禍,因為 harness.h 有段 macro 會把 free 換成一個自己開發的函式,導致你用不到真正的 free ,變成在用 malloc 與 test_free ,因此直接用 malloc 讓 preprocessor 把它也轉成 test_malloc 就好了。
pjchiou2018 Sep 27 Thu 05:58我試一下用 malloc
butastur-rtos2018 Sep 27 Thu 08:43
修改 q_size 的傳回值
實作 q_reverse 要注意兩點, 第一, 不可以增加 list_ele_t的欄位來作雙方鏈結, 第二, 不可以對 list 的 element 作allocate or free, 只可以 rearrange the existing ones.
初期的想法是分兩個步驟:
第一, 從 tail 開始, 每一個 list_ele_t 的 next 都指向前一個 list_ele_t
第二, 等每一個 list_ele_t 的 next 都指向前一個之後, swap q->head 和 q->tail
以上兩個步驟好像太普通,我想試試以下這個方法, 節錄自 include/linux/list.h
[source
]
不過再仔細看一下, 這個方法不行, 因為這是用在 doubly linked list
如果用以下的順序, 寫出來會更糟或是一般般呢? 先畫成 Graph 思考一下
如果用這個方法, 寫出來會更糟或是一般般呢? 繼續實驗…
qtest
測試的結果是
make test
的結果是
但是這樣寫的效能太差, 所以 Time limit exceeded, 這樣寫會導致效能慢也是可以預期的, 畢竟每次找prev都是從頭開始找
由於效能太差, 所以要思考一下有什麼改善的方法?
或許可以不只用
prev
,多用幾個 pointers 記錄
LawrenceSun, Sep 23, 2018 3:50 PM多用兩個 pointer 果然有效
butastur-rtosThu, Sep 27, 2018 8:46 PM
上面這個流程只用一個 prev
並沒有辦法完成, 所以看起來加一個 prev
不夠, 如 Lawrence 建議再加2個 pointers 試試看, 一個 current
, 代表 prev
的下一個, 一個 next
, 指向 current
的下一個
先將目前進度 commit
使用3個 pointers 來紀錄 element of list 後效能有提升
設定SSH, 然後使用 vim 編輯 message 後再 commit
所以 github 上的 authenticating 要再改一下
q_reverse 在不使用 doubly linked list 的前提下, 試過以現有的q->head, q->tail來實作, 但是效能太低, 試過只加一個 pointer prev 來實作, 但是程式複雜度提高, 最後加了3個pointers prev, current, next 這三個pointer, 在對每一個 element 作 reverse 的時候, 來紀錄 element 的前後兩個 element 的address, 最後解決了這個效能的問題, 這個解法是在不使用 doubly linked list 的前提下, 網路上常見的寫法
以下這個 error, 會使用 qtest
來 debug, 並用這個 error 來說明 qtest
看一下 trace-06-string 作了什麼測試
一步一步的執行, 直到第28行的 reverse 產生一個 Segmentation fault, 所以從 q_reverse 來檢查一下
在第 4 行加上 NULL 的判斷
測試結果
目前實作碼的品味不夠, 在9/27(四)之前應該要再把目前的實作碼改的比較有品味
butastur-rtos
用 valgrind
來檢查一下 qtest
的執行結果有沒有 memory leak
對 valgrind
多一些嘗試, 試一下 valgrind --leak-check=full
說明 qtest
的行為
butastur-rtos
100/100 PASS
qtest detect 到 corruption 時會出現以下 訊息, 接著說明 qtest 是如何辦到這件事的
qtest 在 free 的時候, 實際上是執行 test_free, 這個 function 會呼叫 find_header, find_footer, 通過判斷 block 的 footer, 如果不是 0xbeefdead(也就是MAGICFOOTER), 就會被視為 Corruption detected
接下來解釋 block, footer, 以及說明 test_malloc, find_header, find_footer 彼此之間是如何動作的
大致上, test_malloc 的時候除了會 allocate 一段預定大小的記憶體之外, 會另外 allocate 一段記憶體 for block_ele_t
但是另外再 allocate sizeof(size_t)
是為了什麼呢?
test_malloc 在成功 allocate 一段位址後, 會作以下 6 件事
sizeof(size_t)
的原因, 因為要放 MAGICFOOTER自動測試機制是否可以理解為 TDD?
持續更新中…
sysprog2018