contributed by < Holychung
>
2020q3 Homework1 (lab0) 題目
詳細閱讀 C Programming Lab ,依據指示著手修改 queue.[ch] 和連帶的檔案,測試後用 Git 管理各項修改,記得也該實作 q_sort 函式。
q_new
: 建立新的「空」佇列;q_free
: 釋放佇列所佔用的記憶體;q_insert_head
: 在佇列開頭 (head) 加入 (insert) 給定的新元素 (以 LIFO 準則);q_insert_tail
: 在佇列尾端 (tail) 加入 (insert) 給定的新元素 (以 FIFO 準則);q_remove_head
: 在佇列開頭 (head) 移除 (remove) 給定的元素。q_size
: 計算佇列中的元素數量。q_reverse
: 以反向順序重新排列鏈結串列,該函式不該配置或釋放任何鏈結串列元素,換言之,它只能重排已經存在的元素;q_sort
: 以遞增順序來排序鏈結串列的元素,可參閱 Linked List Sort 得知實作手法;queue.h
要在 內完成 q_insert_tail
與 q_size
的話,必須在 queue_t
中加入 size
與 tail
。
queue.c
為了達到時間複雜度 ,參考 Linked List Sort 使用 Merge Sort,排序的過程中把 q->head 指向最左邊的位置,排序完後也需額外尋找尾端來更新。
使用 Valgrind 動態程式分析工具,對記憶體進行分析和除錯,使用方式如下。
lab0 已整合 Valgrind 找出記憶體相關的問題,使用方式如下
程式輸出
搭配記憶體分析工具 Massif 使用,Massif 是一個 heap profiler,可以追蹤程式使用 heap memory 的狀況,使用方式如下,更細節可以參考 User Manual 操作。
執行完後,當前目錄底下會出現 massif.out.<執行程式 PID>, 透過 ms_print
顯示分析結果。若程式有正確釋放記憶體,會看到最終記憶體使用量會回到 0。
Massif starts by taking snapshots for every heap allocation/deallocation
然後 snapshots 又分三種:
:
Normal snapshot@
Detail snapshot#
Peak snapshot相比 ms_print,massif-visualizer 有圖形化的介面更方便分析,不過需要額外安裝
使用方式如下
假設在 q_free
當中忘記把 q->head->value 給釋放掉,就會造成 memory leak
可以明顯看出最後的記憶體沒有完全釋放掉,接下來使用 make valgrind
來觀察,可以看到很多記憶體 still reachable,代表程式結束時有未釋放的記憶體,不過卻還有指標指著。
論文閱讀:Dude, is my code constant time?
參照 antirez/linenoise 改善 qtest
命令列。
qtest
命令列功能linenoise 的 API 相當的完善,可以直接應用到 qtest
當中,不過我 fork 作業的時候(9/18 以後)老師已經把 linenoise 整合 merge 進去,所以看到的 code 是已經整合過的>< 不過底下還是稍微提一下 trace 的過程。
先找到 qtest.c
main function 裡面,找到 run_console
的地方,再到 console.c
看到這個函式,run_console
有呼叫到 readline
這個函式,把這邊替換成 linenoise 的 API。
一樣在啟動時要先註冊 callback function,然後這邊會用 cmd_list
去記下輸入過的 command,用 cmd_maybe
去跟現在 buf 的字串比對,如果比對相似就會呼叫 linenoiseAddCompletion
。
這邊在一開始呼叫 linenoiseHistoryLoad
去讀實體的檔案 .cmd_history
,再直接呼叫 linenoise 的 API,每次輸入指令後就加入 history 並且儲存到 HISTORY_FILE
當中。
TODO