2018q1 Homework2 (prefix-search)
contributed by <bauuuu1021
>
開發環境
理解程式碼
- 變數定義
- INS = REF = 0
- DEL = CPY = 1
- tst_ins_del() 中
- 傳入的字串 s 有出現在樹中
- del != 0 : 刪除字串
- del == 0 : refcnt+1
- 傳入的字串 s 沒有出現在樹中
- cpy != 0 : allocate storage for 's'
- cpy == 0 : save pointer to 's'
- 傳入參數 char* const* s
- reference
- s 為一個 pointer to a "const pointer to char"
- gdb 結果
Prefix 缺陷
搜尋城市名問題
- Github
- 因為 input 檔中都是
城市
, 國家
,導致搜尋城市時如果不加 "," 就找不到
- 仿造 rmcrlf() 寫了一個 addComma() ,當第一次搜尋不到時會在字尾加逗號再搜一次,結果如下
刪除不存在的字串會變成輸入
- 發現是在執行 tst_ins_del() 時,只要字串原本不存在就會 insert
修改 FIXME
更改 tst_ins_del() 的參數
- 發現 fix me 註解後接的都是 tst_ins_del() 這個 function,這個函式的前三個參數跟功能有關,應該不能更動。所以將第四個參數改成 REF
- 結果全部建議字串都 == 輸入字串
- 而且結束 (q) 會跳 core dumped
- 參考 HTYISABUG 同學的方法,將
case 'q':
中 tst_free_all(root) 改成 tst_free(root) 即解決。在 tst.c 中,兩個函式只差前者多了這兩行
- 因此推斷是在 free() 的時候出問題,因此在 free() 前後各加上一個 printf(),結果只有前面的字串印出,所以確認為 free() 的時候出問題
早安
ryanpatiency
ㄜ…早安?bauuuu1021
使用 GDB 觀察
- 決定使用 gdb 看一下,以下紀錄一些本來不了解的指令
- 在其他檔案設中斷點 : (gdb)b
file.c
: line or func()
- 逐行執行 : (gdb)s
- 現在位置 : (gdb)frame
- 在使用 gdb 的過程中,執行到有關進入檔案系統或是 malloc 就會有以下情形,所以要把中斷點設在開檔或配置記憶體後面,不然會花很多時間跳過
(gdb) p sgl
$1 = {0x60ae80 "Tai’an,", 0xaf5cf0 "Tai,", 0x1a4dae0 "Taibon", 0x70fca0 "Taicheng,", 0x62d980 "Taichung,",
0x61ef60 "Taiden,", 0x1279cf0 "Taigum,", 0x895a10 "Taikang,", 0x82e830 "Tailai,", 0x19c74d0 "Taillades,",
0xf8b080 "Taillan-Médoc,", 0x1e22410 "Taillecourt,", 0x1562640 "Tain,", 0x63b580 "Tainan,", 0x15e2d80 "Taino,",
0x1891800 "Tainter", 0x1bf6ae0 "Taintrux,", 0xae2bd0 "Taiobeiras,", 0x1a75dd0 "Taipa,", 0x1305010 "Taipalsaari,",
0x608c70 "Taipei,", 0x6bf280 "Taiping,", 0x1343970 "Taipu,", 0x16fcae0 "Tairan", 0x1b0c2d0 "Tairua,",
0x855230 "Taisen-ri,", 0x18d8cc0 "Taissy,", 0x758bc0 "Taitung", 0x132a140 "Taivalkoski,", 0x1a8f010 "Taivassalo,",
0x172d540 "Taiwala,", 0x608d50 "Taiwan", 0x7d6f40 "Taixing,", 0xd66da0 "Taiynsha,", 0x612a90 "Taiyuan,",
0x64aa70 "Taizhou,", 0x0 <repeats 988 times>}
- 發現 suggest 不但字串都相同,指向的位置也相同;又參照 CPY 跟 REF 兩個 case,發現兩者差異只有再有沒有事先 alloc 一塊空間;還發現這句註解
/* save pointer to 's' (allocated elsewhere) */
- 代表另外給字串儲存空間應改可解決
引入 Sbrk
- 打算用 sbrk 在 heap 給一塊空間再存入字串
發現結果完全不對…崩潰= =
決定換方法重來bauuuu1021
引入 memory pool
- 原本在建置 tst 時就會 sigmentation fault ,以 gdb 逐行檢視發現是在 tst.c 的這行被擋下來
- 判斷是在傳到 tst_ins_del() 的字串 s 有問題,多方嘗試後,發現如果先把 pool->current 的值清除即解決
這樣並沒有解決問題,只是那一次的記憶體位置剛好可以運行而已,current 跟 tail 在 struct 中會有自己指向自己的問題,要是不將指向的記憶體位置更改的話你 memAlloc 時就可能會錯誤的把 pool 內部 current 的值改掉。
BodomMoon
感謝指正,BodomMoon 同學共筆中有很詳盡的解說,請大家參考 bauuuu1021
修改 Makefile
前面用的有點灰心QQ,先來嘗試其他要求 bauuuu1021
- 自動輸入命令
- 每個 fgets() 的最後一個參數改成 selectFP
- 如果執行檔後有輸入
--bench <file.txt>
就將 selectFP assign 為測試檔的檔案指標
- 否則 selectFP 設為 stdin 以手動輸入
- Makefile 新增 target,可透過
$make bench
將 "cities.txt" 中全部字串搜尋一次
不知道為甚麼會先 print 完兩個字串才開始執行@@
效能分析
分析工具
- 因為需要針對某段程式碼進行效能分析, perf 好像不支援(有誤的話麻煩打臉!)因此找了一些工具:
- papi
- 需要另外安裝,而且試了一下我的環境好像不支援,放棄
- rdtsc
剛剛在 git commit 的時候因為檔案變很多(那時候QQ),還有一個叫 .vscode 的怪怪東西,想說就把他刪掉好了。結果不知道是下錯指令還是怎樣,整個專案全部88…心已死…大概兩天的心血全部不見= =
奉勸大家真的要
寫到哪上傳到哪
寫到哪上傳到哪
寫到哪上傳到哪
- 提交 commit 時遇到以下問題,是因為沒有將以 FILE* 開的檔 fclose() 的關係,不只是要在程式的結尾加,還有中間要是有某些功能執行失敗及跳出程式也要加。
GNU Plot 製圖
- 教學共筆
- Github
- 可透過
$make plot
製圖
- 以長條圖呈現建立 tst 的時間
- 以點狀分佈圖呈現 prefix-search 時所需 cycle 數發生機率
Memory pool


- 和預先猜測的不太一樣,發現好像並沒有什麼明顯的差異
參考資料