contributed by < ArielWu0203
>
linux_2019
queue_t *
.q new
: Create a new, empty queue.
q free
: Free all storage used by a queue.
q insert head
: Attempt to insert a new element at the head of the queue (LIFO discipline).
q insert tail
: Attempt to insert a new element at the tail of the queue (FIFO discipline).
q remove head
: Attempt to remove the element at the head of the queue.
q size
: Compute the number of elements in the queue.
q reverse
: Reorder the list so that the queue elements are reversed in order. This function should not allocate or free any list elements (either directly or via calls to other functions that allocate or free list elements.) Instead, it should rearrange the existing elements.
意思是改變 pointer 就好,不能 free 或是 allocate elements 。
q_insert_tail
and q_size
require O(1),*tail
and size
field.q new :
void * malloc(int n);
n 為要求的 bytes 數。malloc成功時,則返回 address,malloc 失敗時,則返回 NULL。
malloc 後分配得到的空間是未初始化的。所以在要使用空間時,需用 memset 來初始化為 0。
void * memset (void * p,int c,int n) ;
p 為 address,c 為需要初始化的值(這裡我設定為 0),n 為需要被初始化的 bytes 數。
在 Makefile
中:
所以我去找了 scripts/driver.py
:
在 135 行中 :
getopt
是用來處理命令行參數,
'hp:t:v:A'
表示為 -h -p (參數) -t (參數) -v (參數) -A
'valgrind'
表示為 --valgrind
在 usage(name) function 中:
是用來輸出參數的使用方法。
verbosity level
表示輸出的詳細程度。
-A
: 最後會輸出每個 trace file 的分數 (以 JASON string 形式)
可以用不同的參數來測試,預設為
-p (./qtest)
-t (trace directory 中的所有檔案)
-v 0
-valgrind (false)
-A (false)
在 README
中有提到 :
harness.{c,h}
: Customized version of malloc and free to provide rigorous testing framework (藉由改版過後的 malloc 和 free 來嚴格維護記憶體的使用)
改版過後的 malloc 和 free 是什麼? 去看了 harness.h
後發現:
所以在 qtest.c
裡使用的 malloc 和 free 都是 call test_malloc & test_free function。
test_malloc
function 中:*find_footer
function 中:test_free
function 中:從上面的 code 中,可以發現 MAGICHEADER
MAGICFREE
MAGICFOOTER
用來檢測在 malloc 和 free 時有沒有出錯,還有 FILLCAHR
作為初始化用。 (這些皆為 magic number )
題外話 : 認真看了一下
#define MAGICHEADER 0xdeadbeef
這行,覺得這取名也太特別了,就去 google 了一下,意外查到有趣的小知識,有興趣可以點 link & magic number–wiki
當接收到不同的 signum
參數,會有 handler 來處理。
SIGSEGV
: Invalid memory reference.(想要取一個 NULL 或是不存在的 pointer)
SIGALRM
: Timer signal from ALARM(2).
在 harness.c
中:
Valgrind is a GPL'd system for debugging and profiling Linux programs. With Valgrind's tool suite, you can automatically detect many memory management and threading bugs.
reference
--quiet
: 只打印錯誤
--leak-check=full --show-leak-kinds=all
: check for leak.
使用問題 : 若我執行下列程式,會有 ERROR: Time limit exceeded.
和 ERROR: Freed queue, but 1 blocks are still allocated
訊息。
是超過了可執行時間,所以我去找了 sigalrmhandler
(處理 SIGALRM signal 的 handler function ),發現 call trigger_exception
function :
int sigsetjmp(sigjmp_buf env, int savesigs);
:
link
save stack context for nonlocal goto (意思是會存目前的stack)
return 0 if returning directly, and nonzero when returning from longjmp(3) or siglongjmp(3) using the saved context.
env
: 存 stacksavesigs
: 不為 0 時,也會把 signals 存起來。void siglongjmp(sigjmp_buf env, int val);
:
link
siglongjmp() also restores the signal mask that was saved by sigsetjmp(3)
了解了 siglongjmp
和 siglongjmp
後,在 harness.c
中找到了 siglongjmp
:
會 jump 到最近一次的 exception_setup
,因為藉由 valgrind 發現出錯的地方在 do_insert_head (qtest.c:166)
:
重新回到上次儲存的 stack,這次 exception_setup(true)
回傳 false ,不再 malloc 了,但是上一次exception_setup(true)
回傳的是 true,所以 malloc a block,因為是 dynamic allocate,所以 stack 還原了,但是 block 卻沒有 free !