contributed by <blake11235
>
$ lscpu
Architecture: x86_64
CPU 作業模式: 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
每核心執行緒數:1
每通訊端核心數:4
Socket(s): 1
NUMA 節點: 1
供應商識別號: GenuineIntel
CPU 家族: 6
型號: 158
Model name: Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz
製程: 9
CPU MHz: 800.000
CPU max MHz: 3500.0000
CPU min MHz: 800.0000
BogoMIPS: 4991.82
虛擬: VT-x
L1d 快取: 32K
L1i 快取: 32K
L2 快取: 256K
L3 快取: 6144K
NUMA node0 CPU(s): 0-3
在做程式碼測試時,意外發現了一個奇怪的問題
Commands:
a add word to the tree
f find word in tree
s search words matching prefix
d delete word from the tree
q quit, freeing all data
choice: d
enter word to del: qq
deleting qq
delete failed.
Commands:
a add word to the tree
f find word in tree
s search words matching prefix
d delete word from the tree
q quit, freeing all data
choice: f
find word in tree: qq
found qq in 0.000003 sec.
若是刪除原本不存在的字串時,會直接變成輸入字串
原來也有其他人發現了一樣的問題
解決方式其實不難,只要多一個條件判斷就可以了
if(del)
return""
放在 tst_ins_del() 裡面
…結果反而延伸出另一個問題,程式可以刪除不存在的字了…
how to fix it ?
首先找到在 test_ref.c FIXME 的部份,修改程式內容
/* FIXME: insert reference to each string */
if (!tst_ins_del(&root, &p, INS, CPY)) {
fprintf(stderr, "error: memory exhausted, tst_insert.\n");
fclose(fp);
return 1;
}
由於要分析 CPY 和 REF 的不同,在有 tst_ins_del()
函式的地方進行修改
- tst_ins_del(&root, &p, INS, CPY)
+ tst_ins_del(&root, &p, INS, REF)
結果 make 之後出現了幾個問題
find words matching prefix (at least 1 char): Tai
Tai - searched prefix in 0.000515 sec
suggest[0] : Tai
suggest[1] : Tai
suggest[2] : Tai
suggest[3] : Tai
suggest[4] : Tai
suggest[5] : Tai
...
使用 prefix search 時無法正確找到
*** Error in `./test_ref': free(): invalid pointer: 0x00007fffa910a720 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f6bbaeea7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f6bbaef337a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f6bbaef753c]
./test_ref[0x4012b6]
./test_ref[0x4019d8]
./test_ref[0x4010e4]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f6bbae93830]
./test_ref[0x4008e9]
刪除字的時候會 core dumped
*** Error in `./test_ref': free(): invalid pointer: 0x00007ffe279ca700 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fe95af287e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fe95af3137a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fe95af3553c]
./test_ref[0x401fdb]
./test_ref[0x401fb0]
找到 tst_ins_del() 的程式碼 並且找到了有 REF 的地方
/* Place nodes until end of the string, at end of stign allocate
* space for data, copy data as final eqkid, and return.
*/
if (*p++ == 0) {
if (cpy) { /* allocate storage for 's' */
const char *eqdata = strdup(*s);
if (!eqdata)
return NULL;
curr->eqkid = (tst_node *) eqdata;
return (void *) eqdata;
} else { /* save pointer to 's' (allocated elsewhere) */
curr->eqkid = (tst_node *) *s;
return (void *) *s;
}
}
這段程式碼主要是在 tree 字元一個個數入之後,在字串全部輸完之後在最後一個結點 allocte 一個存放位置的空間並且回傳位置。
首先先嘗試前人的作法,在 test_ref.c 當中一開始建立 TST 的時候使用 strdup() 動態分配一個位置給 p
while ((rtn = fscanf(fp, "%s", word)) != EOF) {
char *p = strdp(word);
/* FIXME: insert reference to each string */
if (!tst_ins_del(&root, &p, INS, REF)) {
fprintf(stderr, "error: memory exhausted, tst_insert.\n");
fclose(fp);
return 1;
}
idx++;
}
原本以為程式碼完整了,但竟然還是有問題!!
那麼就針對所有會使用到 tst_ins_del() 前面的 word 使用 strdup() 給他一個新的空間
完成了最基本的程式修改,可以進行效能分析了
city輸入方式