contributed by < horseface1110 >
{%hackmd NrmQUGbRQWemgwPfhzXj6g %}
$ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Address sizes: 40 bits physical, 48 bits virtual
Byte Order: Little Endian
CPU(s): 1
On-line CPU(s) list: 0
Vendor ID: GenuineIntel
Model name: QEMU Virtual CPU version 2.5+
CPU family: 15
Model: 107
Thread(s) per core: 1
Core(s) per socket: 1
Socket(s): 1
Stepping: 1
BogoMIPS: 5199.99
Flags: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx lm constant_tsc nopl xtopo
logy cpuid tsc_known_freq pni ssse3 cx16 sse4_1 sse4_2 x2apic popcnt aes hypervisor lahf_lm cpuid_fault pti
Virtualization features:
Hypervisor vendor: KVM
Virtualization type: full
Caches (sum of all):
L1d: 32 KiB (1 instance)
L1i: 32 KiB (1 instance)
L2: 4 MiB (1 instance)
L3: 16 MiB (1 instance)
NUMA:
NUMA node(s): 1
NUMA node0 CPU(s): 0
Vulnerabilities:
Itlb multihit: KVM: Mitigation: VMX unsupported
L1tf: Mitigation; PTE Inversion
Mds: Vulnerable: Clear CPU buffers attempted, no microcode; SMT Host state unknown
Meltdown: Mitigation; PTI
Spec store bypass: Vulnerable
Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Spectre v2: Mitigation; Retpolines, STIBP disabled, RSB filling
Srbds: Not affected
Tsx async abort: Not affected
commit:76f27e2
/* Free all storage used by queue */
void q_free(struct list_head *head) {
element_t *entry, *safe;
list_for_each_entry_safe(entry, safe, head, list) {
if (entry->value) {
free(entry->value);
}
free(entry);
}
free(head);
}
發現list.h有一個function:q_release_element
,之前忘記檢查head是否為空,新增
if (!head || list_empty(head)) {
free(head);
return;
}
commit:9359749
一開始的用list_empty()檢查是否為空,新分配空間後,再檢查是否有成功分配,最後用list_add
添加節點在頭部。
但發現無法正確執行插入,我想是沒有檢查是否成功放入值到新的節點
所以新增了檢查的函式。
if (!new->value) {
free(new);
return false;
}
commit:f8f5cf2
commit:c2cd219
inser_tail跟remove_tail是一起做的
功能描述:
實作細節:
Commit:6f51bb3
邏輯重點:偶數個節點的話,是刪除正中間的下一個,一開始寫錯,會抓到前一個
commit:f2e792f
struct list_head *merge(struct list_head *left, struct list_head *right, bool descend){
left->prev->next = NULL;
right->prev->next = NULL;
struct list_head *head = NULL, *ptr = head, *current = head;
/*head 是 dummy node,ptr是目前被移出的節點,current是新串列的尾巴*/
while(left && right){
if(compare(left, right, descend)){
ptr = left;
left = left->next;
list_del_init(ptr);
current->next = ptr;
ptr->prev = current;
current = current->next;
}else{
ptr = right;
right = right->next;
list_del_init(ptr);
current->next = ptr;
ptr->prev = current;
current = current->next;
}
}
if(left){
current->next = left;
}else{
current->next = right;
}
return head;
}
segmetation fault
Commit:8feb2a4
實作細節:
困難:
current = head
並在迴圈中current = current->prev
,不直觀,改為head = head->prev->prev
q_release_element
l = [c a d c b a]
cmd> descend
l = [ ... ]
ERROR: Queue has more than 0 elements
Freeing queue
更改為return q_size(head)
即可
直接使用q_reverseK
Commit:853e3cd
- struct list_head *start = NULL, *end = NULL, *current = NULL;
+ struct list_head *start = head, *end = NULL, *current = start;
遇到segmentation fault
發現:index = 0 要放在 index == k 時
current會指向現在檢查到的最後一個,但 q_reverse_segment後,他指向的node不變,導致錯誤
q_merge一次合併兩個queue,直到全部都合併完,使用了merge_lists_with_sentinel_node
,前半部分跟merge很像,但不用斷頭,直接用L1的頭當回傳的頭,最後把L2的頭初始化
##3 q_descend
直接從倒數第二個開始檢查,若大於等於max,保留並更新max;小於max,則刪除
但會遇到
l = [c a d c b a]
cmd> descend
l = [ ... ]
ERROR: Queue has more than 0 elements
Freeing queue
更改為return q_size(head)
即可
Commit:853e3cd
queue.c:152:43: error: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [-Werror=int-conversion]
152 | if(*entry->value != head & strcmp(*entry->value, *safe->value) == 0){
| ^~~~~~~~~~~~~
| |
| char
Strcmp的參數為指標
錯誤:
queue.c:152:26: error: comparison between pointer and integer [-Werror]
152 | if(*entry->value != head & strcmp(*entry->value, *safe->value) == 0){
*entry->value 改為 entry->list.next
錯誤:
queue.c:161:22: error: passing argument 1 of ‘list_del’ from incompatible pointer type [-Werror=incompatible-pointer-types]
161 | list_del(entry);
| ^~~~~
| |
| element_t *
list_del(entry->list.next->prev);,目標:移除當下的node
最後:需要先sort才能使用
錯誤:
l = [b r b r b r a]
cmd>
cmd> dedup
ERROR: Duplicate strings are in queue or distinct strings are not in queue
l = [a]
Freeing queue
/* Swap every two adjacent nodes */
void q_swap(struct list_head *head)
{
// https://leetcode.com/problems/swap-nodes-in-pairs/
q_reverseK(head, 2);
}
reverseK修好就好了
Commit 156c254
rebase後,commit 遇到問題,說是printf出壞東西
oloomb@oloomb:~/linux2025/tmp/tmp/lab0-c$ git commit -a
--- modified dudect/fixture.c
+++ expected coding style
@@ -75,7 +75,7 @@ static void update_statistics(const int6
/* do a t-test on the execution time */
t_push(t, difference, classes[i]);
}
-}
+}
static bool report(void)
{
[!] dudect/fixture.c does not follow the consistent coding style.
Make sure you indent as the following:
clang-format -i dudect/fixture.c
Following files were changed:
- dudect/fixture.c : 1 insertions(+), 1 deletions(-)
Running fmtscan...
No dictionary found.
[!] Check format strings for spelling
執行sudo apt install wamerican
後問題解決,是他的字典
原本的diot中沒有先進行排序,就直接進入update_statistics,導致依據這些閾值裁剪的操作失準。這會使得統計上下文中 t 值、t_cropped 的數據累計出錯,進而導致最終的 t-test 結果不可靠,也就是說可能錯誤判定目標函式是否具有常數時間行為。所以我在這邊加了一個排序prepare_percentiles(exec_times);
,但出現segmentation fault
,我猜想問題是在使用 t_cropped 或 t_second_order 前,沒有分配及初始化它們導致的。
static void init_once(void)
{
init_dut();
t_init(t);
+ for (size_t i = 0; i < DUDECT_NUMBER_PERCENTILES; i++) {
+ t_cropped[i] = malloc(sizeof(t_context_t));
+ if (!t_cropped[i]) die();
+ t_init(t_cropped[i]);
+ }
+ t_second_order = malloc(sizeof(t_context_t));
+ if (!t_second_order) die();
+ t_init(t_second_order);
}
Commit db4bd7b
雖然這樣可以通過測驗,但我心裡不踏實,因為只對exec_time
排序,讓exec_time
和classes
脫鉤了。所以我改了prepare_percentiles
,用結構保存 exec_times 與 classes 的對偶型別
typedef struct {
int64_t exec_time;
uint8_t cls;
} pair_t;
再把有效區間複製資料到 pairs 陣列,排序完後再更新原始陣列