yellow-hank
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 2021q1 Homework1 (lab0) contributed by < `yellow-hank` > ###### tags: `LinuxKernel` :::danger 注意書寫規範:中英文間用一個半形空白字元區隔 :notes: jserv ::: ## Queue 實作 ### Structure ### queue ```cpp typedef struct { list_ele_t *head; /* Linked list of elements */ list_ele_t *tail; /* End of list */ size_t size; /* list size */ } queue_t; ``` #### linked list ```cpp typedef struct ELE { /* Pointer to array holding string. * This array needs to be explicitly allocated and freed */ char *value; struct ELE *next; } list_ele_t; ``` ### functions #### q_new :::spoiler code ```cpp /* * Create empty queue. * Return NULL if could not allocate space. */ queue_t *q_new() { queue_t *q = malloc(sizeof(queue_t)); // check malloc whether allocating space sucess or not if (!q) { return q; } q->head = NULL; q->tail = NULL; q->size = 0; return q; } ``` ::: - 產生一個新的 queue 的資料結構,若是配置記憶體失敗,則回傳 NULL ,餅切初始化 queue 的變數 #### q_free :::spoiler code ```cpp /* Free all storage used by queue */ void q_free(queue_t *q) { if (!q) { return; } /* go through each list node to release value's space. * After release value's space, release list node */ for (; q->head != NULL;) { free(q->head->value); list_ele_t *delete_node = q->head; q->head = q->head->next; free(delete_node); } free(q); } ``` ::: **釋放一個 queue ,裡面有兩個節點的示意圖** ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> delete_node"]; struct2 [label="<f0> head"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct3; struct3:f1 -> struct4; } ``` 更改第一個 next 指向方式,並且讓 head 指向下一個節點 ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> delete_node"]; struct2 [label="<f0> head"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct4; } ``` 釋放 delete_node 指向的空間,並且讓 delete_node 指向下一個節點 ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> delete_node"]; struct2 [label="<f0> head"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct3; } ``` #### q_insert_head :::spoiler code ```cpp /* * Attempt to insert element at head of queue. * Return true if successful. * Return false if q is NULL or could not allocate space. * Argument s points to the string to be stored. * The function must explicitly allocate space and copy the string into it. */ bool q_insert_head(queue_t *q, char *s) { list_ele_t *newh; char *s_new; // check malloc whether allocating space sucess or not if (!q) { return false; } newh = malloc(sizeof(list_ele_t)); if (!newh) { return false; } // allocate space for string s_new = malloc(sizeof(char) * (strlen(s) + 1)); if (!s_new) { free(newh); return false; } // deal with the first time inserting node if (!q->head) { q->tail = newh; } newh->next = q->head; q->head = newh; newh->value = s_new; /*using memcpy because strcpy may cause source string won't * have a teminating character and it may crash program. */ memcpy(s_new, s, strlen(s) + 1); q->size++; return true; } ``` ::: - 這裡使用 memcpy ,是因為 strcpy 會導致 '\0' 有機會不會被放入,可能會使程式存取到非法的空間,使程式終止。 - 在進行除錯時,發現如果在第二次配置記體失敗時,要記得將先前配置的空間釋放掉,第一次撰寫未注意到導致測試未通過。 **示意圖** ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> newh"]; struct2 [label="<f0> head"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct4; } ``` ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> newh"]; struct2 [label="<f0> head"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct3:f1 -> struct4:f0; struct2:f1 -> struct4; } ``` ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> newh"]; struct2 [label="<f0> head"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct3:f1 -> struct4:f0; struct2:f1 -> struct3; } ``` #### q_insert_tail :::spoiler code ```cpp /* * Attempt to insert element at tail of queue. * Return true if successful. * Return false if q is NULL or could not allocate space. * Argument s points to the string to be stored. * The function must explicitly allocate space and copy the string into it. */ bool q_insert_tail(queue_t *q, char *s) { list_ele_t *newh; char *s_new; if (!q) { return false; } newh = malloc(sizeof(list_ele_t)); if (!newh) { return false; } s_new = malloc(sizeof(char) * (strlen(s) + 1)); if (!s_new) { free(newh); return false; } newh->next = NULL; if (q->tail) { q->tail->next = newh; } else { q->head = newh; } q->tail = newh; newh->value = s_new; /*using memcpy because strcpy may cause source string won't * have a teminating character and it may crash program. */ memcpy(s_new, s, strlen(s) + 1); q->size++; return true; } ``` ::: - 這裡使用 memcpy ,是因為 strcpy 會導致 '\0' 有機會不會被放入,可能會使程式存取到非法的空間,使程式終止。 - 為了實現時間複雜度為 O(1) ,在 queue 的結構中加入一個變數紀錄 list 的末端,如此一來,可以在常數時間內加入資料在末端。 **示意圖** ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> head"]; struct2 [label="<f0> tail"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct4; struct3:f1 -> struct4:f0; } ``` ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> head"]; struct2 [label="<f0> tail"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct5 [label="<f0> newh"]; struct6 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct4; struct3:f1 -> struct4:f0; struct5:f1 -> struct6; } ``` ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> head"]; struct2 [label="<f0> tail"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct5 [label="<f0> newh"]; struct6 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct4; struct3:f1 -> struct4:f0; struct5:f1 -> struct6; struct4:f1 -> struct6:f0; } ``` ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> head"]; struct2 [label="<f0> tail"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct5 [label="<f0> newh"]; struct6 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct6; struct3:f1 -> struct4:f0; struct5:f1 -> struct6; struct4:f1 -> struct6:f0; } ``` #### q_remove_head :::spoiler code ```cpp /* * Attempt to remove element from head of queue. * Return true if successful. * Return false if queue is NULL or empty. * If sp is non-NULL and an element is removed, copy the removed string to *sp * (up to a maximum of bufsize-1 characters, plus a null terminator.) * The space used by the list element and the string should be freed. */ bool q_remove_head(queue_t *q, char *sp, size_t bufsize) { list_ele_t *delete_ptr; if (!q) { return false; } if (!q->head) { return false; } if (sp) { memcpy(sp, q->head->value, bufsize); sp[bufsize - 1] = '\0'; } free(q->head->value); delete_ptr = q->head; q->head = q->head->next; free(delete_ptr); q->size--; return true; } ``` ::: - 這裡需要注意的是節點中的 value 需要被釋放,因為先前是透過 malloc 配置,若不進行釋放記憶體使用量會隨時間增加,可能會導致記憶體不足的情況 - 先釋放 value 空間,而後釋放整個節點。 **示意圖** ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> head"]; struct2 [label="<f0> delete_ptr"]; struct3 [label="<f0> tail"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct5 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct4; struct2:f1 -> struct4; struct3:f1 -> struct5:f0; struct4:f1 -> struct5:f0; } ``` ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> head"]; struct2 [label="<f0> delete_ptr"]; struct3 [label="<f0> tail"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct5 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct5; struct2:f1 -> struct4; struct3:f1 -> struct5:f0; } ``` ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> head"]; struct3 [label="<f0> tail"]; struct5 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct5; struct3:f1 -> struct5:f0; } ``` #### q_size :::spoiler code ```cpp /* * Return number of elements in queue. * Return 0 if q is NULL or empty */ int q_size(queue_t *q) { /* using a variable in queue_t to store size.After insert or remove * operation increase or decrease size.With this implement, to reach time * complexity O(1) */ if (!q) { return 0; } return q->size; } ``` ::: - 為了實現時間複雜度為 O(1) ,在 queue 的結構中加入一個變數紀錄節點的個數,而個數的增加或減少則是在新增函示或是移除函示中進行變動。 - 注意的是 queue 為空時,個數為零。 #### q_reverse :::spoiler code ```cpp /* * Reverse elements in queue * No effect if q is NULL or empty * This function should not allocate or free any list elements * (e.g., by calling q_insert_head, q_insert_tail, or q_remove_head). * It should rearrange the existing ones. */ void q_reverse(queue_t *q) { list_ele_t *prev = NULL, *current, *next, *swap; if (!q) { return; } for (current = q->head; current != NULL;) { next = current->next; current->next = prev; prev = current; current = next; } swap = q->head; q->head = q->tail; q->tail = swap; } ``` ::: **示意圖** 用三個指標個別指向三個個別節點 ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> prev"]; struct2 [label="<f0> current"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct5 [label="<f0> next"]; struct6 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct4; struct3:f1 -> struct4:f0; struct5:f1 -> struct6; struct4:f1 -> struct6:f0; } ``` 把個別指向的節點中的 next 指向反向, current 指向 prev , next 指向 current ```graphviz digraph structs { node[shape=record] struct1 [label="<f0> prev"]; struct2 [label="<f0> current"]; struct3 [label="{<f0> value|<f1> next\n}"]; struct4 [label="{<f0> value|<f1> next\n}"]; struct5 [label="<f0> next"]; struct6 [label="{<f0> value|<f1> next\n}"]; struct1:f1 -> struct3; struct2:f1 -> struct4; struct4:f1 -> struct3:f0; struct5:f1 -> struct6; struct6:f1 -> struct4:f0; } ``` #### q_sort :::spoiler code ```cpp /* insert node at list tail and change head and tail pointer*/ void list_insert_tail(list_ele_t **head, list_ele_t **tail, list_ele_t *node) { if (*tail == NULL) { *tail = node; *head = node; } else { (*tail)->next = node; (*tail) = node; } } list_ele_t *merge(list_ele_t *first, list_ele_t *second) { list_ele_t *result_head = NULL, *result_tail = NULL; while (first && second) { // compare and put the smaller one in result if (strcmp(first->value, second->value) <= 0) { list_insert_tail(&result_head, &result_tail, first); first = first->next; } else { list_insert_tail(&result_head, &result_tail, second); second = second->next; } } // Find the list that still have data, and add it in result if (first) { list_insert_tail(&result_head, &result_tail, first); } if (second) { list_insert_tail(&result_head, &result_tail, second); } return result_head; } list_ele_t *mergesort(list_ele_t *list) { if (!list->next) { return list; } list_ele_t *slow = list, *fast = list->next; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; } list_ele_t *tmp = slow->next; slow->next = NULL; return merge(mergesort(list), mergesort(tmp)); } /* * Sort elements of queue in ascending order * No effect if q is NULL or empty. In addition, if q has only one * element, do nothing. */ void q_sort(queue_t *q) { if (!q || !q->head || !q->head->next) { return; } list_ele_t *i; q->head = mergesort(q->head); // update tail's information for (i = q->head; i->next != NULL; i = i->next) ; q->tail = i; } ``` ::: - 第一次實作時使用 Quick Sort , 尚未注意到測試中有考慮到時間複雜度需要達到 O(nlgn) , Quick Sort 最差的時間複雜度會是 O(n^2^) 。為了達成目標,我去尋找較為接近的演算法,後來選擇 Merge Sort , 平均時間複雜度為 O(nlgn) ,在實作中遇到的問題是很容易發生 segmentation fault ,需要了解出錯的地點,很容易在這邊打轉。 - 第一次將 Merge Sort 實作出來,但是因為在加入節點的設計使用到重頭開始移動到尾巴再將其加入,這樣耗費許多時間,雖然結果是正確的。後來,我新增一個變數紀錄尾巴,如同上述 q_insert_tail 的做法,減少許多時間。 ## 修正 qtest 使用 Adress Sanitizer 分析 qtest 執行 help 指令發生的錯誤 ``` ==234967==ERROR: AddressSanitizer: global-buffer-overflow on address 0x557eaae33400 at pc 0x557eaae1c90f bp 0x7ffcc876bad0 sp 0x7ffcc876bac0 READ of size 4 at 0x557eaae33400 thread T0 #0 0x557eaae1c90e in do_help_cmd /home/yellowhank/Desktop/linux_kernel/hw0/lab0-c/console.c:307 #1 0x557eaae1ca22 in interpret_cmda /home/yellowhank/Desktop/linux_kernel/hw0/lab0-c/console.c:221 #2 0x557eaae1d207 in interpret_cmd /home/yellowhank/Desktop/linux_kernel/hw0/lab0-c/console.c:244 #3 0x557eaae1e951 in run_console /home/yellowhank/Desktop/linux_kernel/hw0/lab0-c/console.c:660 #4 0x557eaae1b531 in main /home/yellowhank/Desktop/linux_kernel/hw0/lab0-c/qtest.c:788 #5 0x7f19f18b10b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2) #6 0x557eaae18b8d in _start (/home/yellowhank/Desktop/linux_kernel/hw0/lab0-c/qtest+0x8b8d) 0x557eaae33401 is located 0 bytes to the right of global variable 'echo' defined in 'console.c:59:13' (0x557eaae33400) of size 1 SUMMARY: AddressSanitizer: global-buffer-overflow /home/yellowhank/Desktop/linux_kernel/hw0/lab0-c/console.c:307 in do_help_cmd Shadow bytes around the buggy address: 0x0ab0555be630: f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 0x0ab0555be640: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 0x0ab0555be650: f9 f9 f9 f9 00 00 00 00 04 f9 f9 f9 f9 f9 f9 f9 0x0ab0555be660: 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 0x0ab0555be670: 01 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9 =>0x0ab0555be680:[01]f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 0x0ab0555be690: 04 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00 0x0ab0555be6a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0ab0555be6b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0ab0555be6c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0ab0555be6d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==234967==ABORTING ``` 這裡發現在存取 echo 變數時,會發生 global-buffer-overflow 。查詢 C99 規格書發現 bool 的空間是足夠放 0 和 1 。 - C99 [6.2.5] **Types** > An object declared as type _Bool is large enough to store the values 0 and 1. 下列程式碼使用 plist->valp 整數指標去指向 echo 空間,會導致指標直接存取 4bytes 的空間,但是實際上 echo 的空間不足 4bytes ,會導致 global-buffer-overflow ```cpp report(1, "\t%s\t%d\t%s", plist->name, *plist->valp, plist->documentation); ``` 也實測 bool 和 int 的空間大小,得到 bool 1bytes, int 4 bytes ```cpp printf("%ld %ld\n",sizeof(bool), sizeof(int)) // 1 4 ``` ### 嘗試解決方式 - 可以將 echo 變數的宣告型態提升至 int ,但是接下來 simulation 會遇到相同的問題, simulation 是外部的變數,不一定能夠更動型態。 - 把 plist->valp 轉型成 bool* ,但是需注意到原本是 int* ,這是非常危險的方式,有機會導致資訊量減少,得到錯誤的結果,這個方式需要評估原本的 int 有沒有超過 1bytes 的空間,在這裡因為 option length 使用數字 1024 ,所以不適用。 ### 解決方式 - 在結構 PELE 中加入一個變數紀錄是布林值還是整數值 ```cpp struct PELE { char *name; int *valp; char *documentation; /* Function that gets called whenever parameter changes */ setter_function setter; param_ptr next; bool checkboolint; }; ``` - 在加入參數時,設定此值是布林值還是整數值 ```cpp void add_param(char *name, int *valp, char *doccumentation, setter_function setter); setter_function setter, bool setbool); ``` - 在 report 的地方分為布林值解決方式或是整數值解決方式 ```cpp if (plist->checkboolint) report(1, "\t%s\t%d\t%s", plist->name, *(bool *) plist->valp, plist->documentation); else report(1, "\t%s\t%d\t%s", plist->name, *plist->valp, plist->documentation); ``` ## 使用 valgrind 排除 queue 實作時記憶體錯誤 使用 make valgrind 針對記憶體進行除錯 - 錯誤結果 (擷取第一個測試錯誤) ``` +++ TESTING trace trace-01-ops: # Test of insert_head and remove_head ==288083== Invalid read of size 8 ==288083== at 0x4842C30: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8ff8 is 8 bytes before a block of size 2,049 alloc'd ==288083== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10B3B4: do_remove_head (qtest.c:334) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== ==288083== Invalid read of size 8 ==288083== at 0x4842C3B: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8ff0 is 16 bytes before a block of size 2,049 alloc'd ==288083== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10B3B4: do_remove_head (qtest.c:334) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== ==288083== Invalid read of size 8 ==288083== at 0x4842C1C: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8fe8 is 24 bytes before a block of size 2,049 alloc'd ==288083== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10B3B4: do_remove_head (qtest.c:334) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== ==288083== Invalid read of size 8 ==288083== at 0x4842C28: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8fe0 is 32 bytes before a block of size 2,064 in arena "client" ==288083== ==288083== Invalid read of size 8 ==288083== at 0x4842A8F: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8c50 is 3 bytes after a block of size 45 alloc'd ==288083== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10DEDF: test_malloc (harness.c:138) ==288083== by 0x10E399: q_insert_head (queue.c:64) ==288083== by 0x10BC57: do_insert_head (qtest.c:216) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== ==288083== Invalid read of size 8 ==288083== at 0x4842A97: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8c58 is 11 bytes after a block of size 45 alloc'd ==288083== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10DEDF: test_malloc (harness.c:138) ==288083== by 0x10E399: q_insert_head (queue.c:64) ==288083== by 0x10BC57: do_insert_head (qtest.c:216) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== ==288083== Invalid read of size 8 ==288083== at 0x4842A7C: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8c60 is 19 bytes after a block of size 45 alloc'd ==288083== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10DEDF: test_malloc (harness.c:138) ==288083== by 0x10E399: q_insert_head (queue.c:64) ==288083== by 0x10BC57: do_insert_head (qtest.c:216) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== ==288083== Invalid read of size 8 ==288083== at 0x4842A87: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba8c68 is 24 bytes after a block of size 48 in arena "client" ==288083== ==288083== Invalid read of size 1 ==288083== at 0x4842B60: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10E4DF: memcpy (string_fortified.h:34) ==288083== by 0x10E4DF: q_remove_head (queue.c:144) ==288083== by 0x10B57A: do_remove_head (qtest.c:368) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Address 0x4ba9040 is 64 bytes inside a block of size 2,049 free'd ==288083== at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10B68D: do_remove_head (qtest.c:413) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== Block was alloc'd at ==288083== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==288083== by 0x10B3B4: do_remove_head (qtest.c:334) ==288083== by 0x10CEA1: interpret_cmda (console.c:224) ==288083== by 0x10D338: interpret_cmd (console.c:247) ==288083== by 0x10DBA0: cmd_select (console.c:601) ==288083== by 0x10DE6D: run_console (console.c:674) ==288083== by 0x10C2D1: main (qtest.c:789) ==288083== --- trace-01-ops 0/6 ``` - 問題分析 - 發現在 q_remove_head 中的 memmove 有發生 invalid read 的情況 ### 嘗試解決方式 - 閱讀資料針對 memcpy 可能發生的問題進行解決,在規格書中發現 memcpy 和 memmove 雖然都是複製字串,但是 memcpy 針對 [overlapping](https://cs50.stackexchange.com/questions/14615/memory-overlap-in-c) 的問題, memcpy 會發生未定義行為。 - C99 [7.21.2.1] **The memcpy function** > The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined. - 相對 memmove 可以針對 overlapping 進行處置,是透過複製到一個暫存的陣列來解決 - C99 [7.21.2.2] **The memmove function** > The memmove function copies n characters from the object pointed to by s2 into the object pointed to by s1. Copying takes place as if the n characters from the object pointed to by s2 are first copied into a temporary array of n characters that does not overlap the objects pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1. - memcpy 的好處是效率快速,前提是沒有 overlapping - 所以將 memcpy 替換成 memmove ### 解決方式 - 發現到 memcpy 中的 size 都是使用 buffersize 並沒有針對 q->head->value 做適度的調整導致 sp 的大小都是 bufsize。 ```cpp memcpy(sp, q->head->value, bufsize); sp[bufsize - 1] = '\0'; ``` - 去檢查原本字串的長度,如果超過 bufsize 則另行處理 ```cpp if (bufsize < string_len + 1) { memmove(sp, q->head->value, bufsize); sp[bufsize - 1] = '\0'; } else { memmove(sp, q->head->value, string_len + 1); sp[string_len] = '\0'; } ``` ### 視覺化 simulation 的記憶體使用量 - 使用 valgrind 中的 massif 進行分析 ```bash valgrind --tool=massif ./qtest -v 3 -f ./traces/trace-17-complexity.cmd #印出結果 ms_print massif.out.258408 ``` - 結果 (直接執行上述實做的 queue) ``` -------------------------------------------------------------------------------- Command: ./qtest -v 3 -f ./traces/trace-17-complexity.cmd Massif arguments: (none) ms_print arguments: massif.out.258408 -------------------------------------------------------------------------------- MB 1.231^ # | # | # | # : : | # : : : | # : : :: : : @ | # : : :: : : @ | # : : :: : : @ : | # :: : : : :: : : @ : : | # : : : :::: : : : @ : : | #: : : : :::: : : : @: : :: | #: : ::: : :::: : : : @: : : :: | #: : ::: : @::::: : : : @::: : : : ::@ | #: : ::: : @ :::: : : : @:: : : : ::@ | #: :: : ::: : : @ :::: : ::: : @:: ::: : : ::@ | #: : : ::: : : @ :::: : :: : @:: :::@: : ::@ | #::: : : :::@: : @ :::: : :: : : : @:: :::@: : ::@ | #:: : : : :::@:::@ : @ ::::::: : :: : : : @:: :::@: ::::@ | #:: : : : :::@:::@ : @ ::::: : : :: ::: ::@:: :::@: ::::@ | #:: : : : :::@:::@:: @ : @ ::::: : ::::: :::@@::@:: :: :::@::::::@ 0 +----------------------------------------------------------------------->Gi 0 26.97 Number of snapshots: 65 Detailed snapshots: [1, 2 (peak), 14, 18, 21, 25, 41, 44, 54, 64] -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 0 0 0 0 0 0 1 451,350,369 304,816 250,300 54,516 0 82.12% (250,300B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->76.75% (233,955B) 0x10DEDF: test_malloc (harness.c:138) | ->41.34% (126,000B) 0x10E375: q_insert_head (queue.c:59) | | ->41.34% (126,000B) 0x10E9FE: measure (constant.c:65) | | ->41.34% (126,000B) 0x10EB7E: doit (fixture.c:136) | | ->41.34% (126,000B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->41.34% (126,000B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->41.34% (126,000B) 0x10CEA1: interpret_cmda (console.c:224) | | ->41.34% (126,000B) 0x10D338: interpret_cmd (console.c:247) | | ->41.34% (126,000B) 0x10DBA0: cmd_select (console.c:601) | | ->41.34% (126,000B) 0x10DE6D: run_console (console.c:674) | | ->41.34% (126,000B) 0x10C2D1: main (qtest.c:789) | | | ->35.36% (107,787B) 0x10E399: q_insert_head (queue.c:64) | | ->35.36% (107,787B) 0x10E9FE: measure (constant.c:65) | | ->35.36% (107,787B) 0x10EB7E: doit (fixture.c:136) | | ->35.36% (107,787B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->35.36% (107,787B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->35.36% (107,787B) 0x10CEA1: interpret_cmda (console.c:224) | | ->35.36% (107,787B) 0x10D338: interpret_cmd (console.c:247) | | ->35.36% (107,787B) 0x10DBA0: cmd_select (console.c:601) | | ->35.36% (107,787B) 0x10DE6D: run_console (console.c:674) | | ->35.36% (107,787B) 0x10C2D1: main (qtest.c:789) | | | ->00.06% (168B) in 1+ places, all below ms_print's threshold (01.00%) | ->02.98% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->02.70% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->02.70% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->02.70% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.29% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->02.38% (7,249B) in 10 places, all below massif's threshold (1.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 2 744,872,031 1,290,600 1,051,284 239,316 0 81.46% (1,051,284B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->80.19% (1,034,939B) 0x10DEDF: test_malloc (harness.c:138) | ->43.18% (557,256B) 0x10E375: q_insert_head (queue.c:59) | | ->43.18% (557,256B) 0x10E9FE: measure (constant.c:65) | | ->43.18% (557,256B) 0x10EB7E: doit (fixture.c:136) | | ->43.18% (557,256B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->43.18% (557,256B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->43.18% (557,256B) 0x10CEA1: interpret_cmda (console.c:224) | | ->43.18% (557,256B) 0x10D338: interpret_cmd (console.c:247) | | ->43.18% (557,256B) 0x10DBA0: cmd_select (console.c:601) | | ->43.18% (557,256B) 0x10DE6D: run_console (console.c:674) | | ->43.18% (557,256B) 0x10C2D1: main (qtest.c:789) | | | ->37.00% (477,515B) 0x10E399: q_insert_head (queue.c:64) | | ->37.00% (477,515B) 0x10E9FE: measure (constant.c:65) | | ->37.00% (477,515B) 0x10EB7E: doit (fixture.c:136) | | ->37.00% (477,515B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->37.00% (477,515B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->37.00% (477,515B) 0x10CEA1: interpret_cmda (console.c:224) | | ->37.00% (477,515B) 0x10D338: interpret_cmd (console.c:247) | | ->37.00% (477,515B) 0x10DBA0: cmd_select (console.c:601) | | ->37.00% (477,515B) 0x10DE6D: run_console (console.c:674) | | ->37.00% (477,515B) 0x10C2D1: main (qtest.c:789) | | | ->00.01% (168B) in 1+ places, all below ms_print's threshold (01.00%) | ->01.27% (16,345B) in 11 places, all below massif's threshold (1.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 3 1,196,716,406 705,968 575,645 130,323 0 4 1,525,314,876 273,712 224,842 48,870 0 5 2,195,497,317 49,640 43,108 6,532 0 6 2,590,737,257 28,976 26,331 2,645 0 7 3,086,439,722 445,488 364,123 81,365 0 8 3,814,260,269 201,520 166,510 35,010 0 9 4,121,127,632 34,864 31,125 3,739 0 10 4,581,428,795 787,120 641,617 145,503 0 11 5,246,308,143 629,680 514,129 115,551 0 12 5,757,754,359 600,040 490,065 109,975 0 13 6,249,528,173 1,058,480 861,461 197,019 0 14 6,579,996,777 274,864 226,034 48,830 0 82.23% (226,034B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->76.29% (209,689B) 0x10DEDF: test_malloc (harness.c:138) | ->41.09% (112,952B) 0x10E375: q_insert_head (queue.c:59) | | ->41.09% (112,952B) 0x10E9FE: measure (constant.c:65) | | ->41.09% (112,952B) 0x10EB7E: doit (fixture.c:136) | | ->41.09% (112,952B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->41.09% (112,952B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->41.09% (112,952B) 0x10CEA1: interpret_cmda (console.c:224) | | ->41.09% (112,952B) 0x10D338: interpret_cmd (console.c:247) | | ->41.09% (112,952B) 0x10DBA0: cmd_select (console.c:601) | | ->41.09% (112,952B) 0x10DE6D: run_console (console.c:674) | | ->41.09% (112,952B) 0x10C2D1: main (qtest.c:789) | | | ->35.17% (96,673B) 0x10E399: q_insert_head (queue.c:64) | | ->35.17% (96,673B) 0x10E9FE: measure (constant.c:65) | | ->35.17% (96,673B) 0x10EB7E: doit (fixture.c:136) | | ->35.17% (96,673B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->35.17% (96,673B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->35.17% (96,673B) 0x10CEA1: interpret_cmda (console.c:224) | | ->35.17% (96,673B) 0x10D338: interpret_cmd (console.c:247) | | ->35.17% (96,673B) 0x10DBA0: cmd_select (console.c:601) | | ->35.17% (96,673B) 0x10DE6D: run_console (console.c:674) | | ->35.17% (96,673B) 0x10C2D1: main (qtest.c:789) | | | ->00.02% (64B) in 1+ places, all below ms_print's threshold (01.00%) | ->03.31% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->02.99% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->02.99% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->02.99% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.32% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->02.64% (7,249B) in 10 places, all below massif's threshold (1.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 15 7,075,699,585 394,544 322,629 71,915 0 16 7,488,785,369 200,112 164,754 35,358 0 17 7,819,253,909 837,352 682,465 154,887 0 18 8,232,339,793 211,304 174,359 36,945 0 82.52% (174,359B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->74.78% (158,014B) 0x10DEDF: test_malloc (harness.c:138) | ->40.28% (85,120B) 0x10E375: q_insert_head (queue.c:59) | | ->40.28% (85,120B) 0x10E9FE: measure (constant.c:65) | | ->40.28% (85,120B) 0x10EB7E: doit (fixture.c:136) | | ->40.28% (85,120B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->40.28% (85,120B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->40.28% (85,120B) 0x10CEA1: interpret_cmda (console.c:224) | | ->40.28% (85,120B) 0x10D338: interpret_cmd (console.c:247) | | ->40.28% (85,120B) 0x10DBA0: cmd_select (console.c:601) | | ->40.28% (85,120B) 0x10DE6D: run_console (console.c:674) | | ->40.28% (85,120B) 0x10C2D1: main (qtest.c:789) | | | ->34.47% (72,830B) 0x10E399: q_insert_head (queue.c:64) | | ->34.47% (72,830B) 0x10E9FE: measure (constant.c:65) | | ->34.47% (72,830B) 0x10EB7E: doit (fixture.c:136) | | ->34.47% (72,830B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->34.47% (72,830B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->34.47% (72,830B) 0x10CEA1: interpret_cmda (console.c:224) | | ->34.47% (72,830B) 0x10D338: interpret_cmd (console.c:247) | | ->34.47% (72,830B) 0x10DBA0: cmd_select (console.c:601) | | ->34.47% (72,830B) 0x10DE6D: run_console (console.c:674) | | ->34.47% (72,830B) 0x10C2D1: main (qtest.c:789) | | | ->00.03% (64B) in 1+ places, all below ms_print's threshold (01.00%) | ->04.30% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->03.89% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->03.89% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->03.89% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.42% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->02.29% (4,849B) in 9 places, all below massif's threshold (1.00%) | ->01.14% (2,400B) 0x10EB30: doit (fixture.c:127) ->01.14% (2,400B) 0x10EDD6: is_insert_tail_const (fixture.c:168) ->01.14% (2,400B) 0x10B7F2: do_insert_tail (qtest.c:263) ->01.14% (2,400B) 0x10CEA1: interpret_cmda (console.c:224) ->01.14% (2,400B) 0x10D338: interpret_cmd (console.c:247) ->01.14% (2,400B) 0x10DBA0: cmd_select (console.c:601) ->01.14% (2,400B) 0x10DE6D: run_console (console.c:674) ->01.14% (2,400B) 0x10C2D1: main (qtest.c:789) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 19 8,810,659,780 65,512 56,001 9,511 0 20 9,471,596,719 48,688 42,333 6,355 0 21 9,884,682,472 91,880 77,400 14,480 0 84.24% (77,400B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->66.45% (61,055B) 0x10DEDF: test_malloc (harness.c:138) | ->35.72% (32,816B) 0x10E375: q_insert_head (queue.c:59) | | ->35.72% (32,816B) 0x10E9FE: measure (constant.c:65) | | ->35.72% (32,816B) 0x10EB7E: doit (fixture.c:136) | | ->35.72% (32,816B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->35.72% (32,816B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->35.72% (32,816B) 0x10CEA1: interpret_cmda (console.c:224) | | ->35.72% (32,816B) 0x10D338: interpret_cmd (console.c:247) | | ->35.72% (32,816B) 0x10DBA0: cmd_select (console.c:601) | | ->35.72% (32,816B) 0x10DE6D: run_console (console.c:674) | | ->35.72% (32,816B) 0x10C2D1: main (qtest.c:789) | | | ->30.55% (28,071B) 0x10E399: q_insert_head (queue.c:64) | | ->30.55% (28,071B) 0x10E9FE: measure (constant.c:65) | | ->30.55% (28,071B) 0x10EB7E: doit (fixture.c:136) | | ->30.55% (28,071B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->30.55% (28,071B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->30.55% (28,071B) 0x10CEA1: interpret_cmda (console.c:224) | | ->30.55% (28,071B) 0x10D338: interpret_cmd (console.c:247) | | ->30.55% (28,071B) 0x10DBA0: cmd_select (console.c:601) | | ->30.55% (28,071B) 0x10DE6D: run_console (console.c:674) | | ->30.55% (28,071B) 0x10C2D1: main (qtest.c:789) | | | ->00.18% (168B) in 1+ places, all below ms_print's threshold (01.00%) | ->09.90% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->08.94% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->08.94% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->08.94% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.96% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->02.61% (2,400B) 0x10EB30: doit (fixture.c:127) | ->02.61% (2,400B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | ->02.61% (2,400B) 0x10B7F2: do_insert_tail (qtest.c:263) | ->02.61% (2,400B) 0x10CEA1: interpret_cmda (console.c:224) | ->02.61% (2,400B) 0x10D338: interpret_cmd (console.c:247) | ->02.61% (2,400B) 0x10DBA0: cmd_select (console.c:601) | ->02.61% (2,400B) 0x10DE6D: run_console (console.c:674) | ->02.61% (2,400B) 0x10C2D1: main (qtest.c:789) | ->01.31% (1,208B) 0x10EAE8: doit (fixture.c:122) | ->01.31% (1,208B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | ->01.31% (1,208B) 0x10B7F2: do_insert_tail (qtest.c:263) | ->01.31% (1,208B) 0x10CEA1: interpret_cmda (console.c:224) | ->01.31% (1,208B) 0x10D338: interpret_cmd (console.c:247) | ->01.31% (1,208B) 0x10DBA0: cmd_select (console.c:601) | ->01.31% (1,208B) 0x10DE6D: run_console (console.c:674) | ->01.31% (1,208B) 0x10C2D1: main (qtest.c:789) | ->01.31% (1,208B) 0x10EAF8: doit (fixture.c:123) | ->01.31% (1,208B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | ->01.31% (1,208B) 0x10B7F2: do_insert_tail (qtest.c:263) | ->01.31% (1,208B) 0x10CEA1: interpret_cmda (console.c:224) | ->01.31% (1,208B) 0x10D338: interpret_cmd (console.c:247) | ->01.31% (1,208B) 0x10DBA0: cmd_select (console.c:601) | ->01.31% (1,208B) 0x10DE6D: run_console (console.c:674) | ->01.31% (1,208B) 0x10C2D1: main (qtest.c:789) | ->01.31% (1,200B) 0x10EB08: doit (fixture.c:124) | ->01.31% (1,200B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | ->01.31% (1,200B) 0x10B7F2: do_insert_tail (qtest.c:263) | ->01.31% (1,200B) 0x10CEA1: interpret_cmda (console.c:224) | ->01.31% (1,200B) 0x10D338: interpret_cmd (console.c:247) | ->01.31% (1,200B) 0x10DBA0: cmd_select (console.c:601) | ->01.31% (1,200B) 0x10DE6D: run_console (console.c:674) | ->01.31% (1,200B) 0x10C2D1: main (qtest.c:789) | ->01.11% (1,024B) 0x4A2AE83: _IO_file_doallocate (filedoalloc.c:101) | ->01.11% (1,024B) 0x4A3B04F: _IO_doallocbuf (genops.c:347) | ->01.11% (1,024B) 0x4A3A0AF: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:745) | | ->01.11% (1,024B) 0x4A38834: _IO_new_file_xsputn (fileops.c:1244) | | ->01.11% (1,024B) 0x4A38834: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1197) | | ->01.11% (1,024B) 0x4A1FAF1: __vfprintf_internal (vfprintf-internal.c:1373) | | ->01.11% (1,024B) 0x10C8C9: vfprintf (stdio2.h:130) | | ->01.11% (1,024B) 0x10C8C9: report_noreturn (report.c:122) | | ->01.11% (1,024B) 0x10DB5E: readline (console.c:534) | | ->01.11% (1,024B) 0x10DB5E: cmd_select (console.c:599) | | ->01.11% (1,024B) 0x10DE6D: run_console (console.c:674) | | ->01.11% (1,024B) 0x10C2D1: main (qtest.c:789) | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | ->00.23% (209B) in 1+ places, all below ms_print's threshold (01.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 22 10,417,751,127 23,984 22,279 1,705 0 23 11,017,665,208 222,640 183,631 39,009 0 24 11,497,596,509 47,792 41,589 6,203 0 25 12,097,510,777 518,248 423,278 94,970 0 81.67% (423,278B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->78.52% (406,933B) 0x10DEDF: test_malloc (harness.c:138) | ->42.34% (219,408B) 0x10E375: q_insert_head (queue.c:59) | | ->42.34% (219,408B) 0x10E9FE: measure (constant.c:65) | | ->42.34% (219,408B) 0x10EB7E: doit (fixture.c:136) | | ->42.34% (219,408B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->42.34% (219,408B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->42.34% (219,408B) 0x10CEA1: interpret_cmda (console.c:224) | | ->42.34% (219,408B) 0x10D338: interpret_cmd (console.c:247) | | ->42.34% (219,408B) 0x10DBA0: cmd_select (console.c:601) | | ->42.34% (219,408B) 0x10DE6D: run_console (console.c:674) | | ->42.34% (219,408B) 0x10C2D1: main (qtest.c:789) | | | ->36.17% (187,461B) 0x10E399: q_insert_head (queue.c:64) | | ->36.17% (187,461B) 0x10E9FE: measure (constant.c:65) | | ->36.17% (187,461B) 0x10EB7E: doit (fixture.c:136) | | ->36.17% (187,461B) 0x10EDD6: is_insert_tail_const (fixture.c:168) | | ->36.17% (187,461B) 0x10B7F2: do_insert_tail (qtest.c:263) | | ->36.17% (187,461B) 0x10CEA1: interpret_cmda (console.c:224) | | ->36.17% (187,461B) 0x10D338: interpret_cmd (console.c:247) | | ->36.17% (187,461B) 0x10DBA0: cmd_select (console.c:601) | | ->36.17% (187,461B) 0x10DE6D: run_console (console.c:674) | | ->36.17% (187,461B) 0x10C2D1: main (qtest.c:789) | | | ->00.01% (64B) in 1+ places, all below ms_print's threshold (01.00%) | ->01.76% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->01.59% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->01.59% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->01.59% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.17% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->01.40% (7,249B) in 10 places, all below massif's threshold (1.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 26 12,457,459,255 580,072 473,733 106,339 0 27 13,057,373,388 970,088 790,451 179,637 0 28 13,417,321,965 764,976 623,253 141,723 0 29 14,017,235,984 1,125,296 916,184 209,112 0 30 14,377,184,366 993,072 809,010 184,062 0 31 14,857,115,714 215,272 177,607 37,665 0 32 15,577,012,612 1,144,552 931,820 212,732 0 33 16,056,943,800 23,656 22,024 1,632 0 34 16,627,378,405 257,840 212,026 45,814 0 35 17,288,316,182 93,104 78,407 14,697 0 36 17,949,253,519 1,027,888 837,327 190,561 0 37 18,279,722,221 388,656 318,568 70,088 0 38 18,940,659,559 261,864 215,480 46,384 0 39 19,601,597,277 134,576 112,087 22,489 0 40 20,097,300,581 725,864 592,461 133,403 0 41 20,427,769,452 125,104 104,329 20,775 0 83.39% (104,329B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->70.33% (87,982B) 0x10DEDF: test_malloc (harness.c:138) | ->37.91% (47,432B) 0x10E375: q_insert_head (queue.c:59) | | ->37.91% (47,432B) 0x10EAA3: measure (constant.c:76) | | | ->37.91% (47,432B) 0x10EB7E: doit (fixture.c:136) | | | ->37.91% (47,432B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->37.91% (47,432B) 0x10AE1A: do_size (qtest.c:482) | | | ->37.91% (47,432B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->37.91% (47,432B) 0x10D338: interpret_cmd (console.c:247) | | | ->37.91% (47,432B) 0x10DBA0: cmd_select (console.c:601) | | | ->37.91% (47,432B) 0x10DE6D: run_console (console.c:674) | | | ->37.91% (47,432B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->32.36% (40,486B) 0x10E399: q_insert_head (queue.c:64) | | ->32.36% (40,486B) 0x10EAA3: measure (constant.c:76) | | | ->32.36% (40,486B) 0x10EB7E: doit (fixture.c:136) | | | ->32.36% (40,486B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->32.36% (40,486B) 0x10AE1A: do_size (qtest.c:482) | | | ->32.36% (40,486B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->32.36% (40,486B) 0x10D338: interpret_cmd (console.c:247) | | | ->32.36% (40,486B) 0x10DBA0: cmd_select (console.c:601) | | | ->32.36% (40,486B) 0x10DE6D: run_console (console.c:674) | | | ->32.36% (40,486B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->00.05% (64B) in 1+ places, all below ms_print's threshold (01.00%) | ->07.27% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->06.57% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->06.57% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->06.57% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.70% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->03.88% (4,851B) in 10 places, all below massif's threshold (1.00%) | ->01.92% (2,400B) 0x10EB30: doit (fixture.c:127) ->01.92% (2,400B) 0x10EEB7: is_size_const (fixture.c:188) | ->01.92% (2,400B) 0x10AE1A: do_size (qtest.c:482) | ->01.92% (2,400B) 0x10CEA1: interpret_cmda (console.c:224) | ->01.92% (2,400B) 0x10D338: interpret_cmd (console.c:247) | ->01.92% (2,400B) 0x10DBA0: cmd_select (console.c:601) | ->01.92% (2,400B) 0x10DE6D: run_console (console.c:674) | ->01.92% (2,400B) 0x10C2D1: main (qtest.c:789) | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 42 21,088,706,911 311,472 255,648 55,824 0 43 21,584,410,151 179,760 148,603 31,157 0 44 22,080,113,397 979,816 797,457 182,359 0 81.39% (797,457B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->79.72% (781,110B) 0x10DEDF: test_malloc (harness.c:138) | ->43.00% (421,344B) 0x10E375: q_insert_head (queue.c:59) | | ->43.00% (421,344B) 0x10EAA3: measure (constant.c:76) | | | ->43.00% (421,344B) 0x10EB7E: doit (fixture.c:136) | | | ->43.00% (421,344B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->43.00% (421,344B) 0x10AE1A: do_size (qtest.c:482) | | | ->43.00% (421,344B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->43.00% (421,344B) 0x10D338: interpret_cmd (console.c:247) | | | ->43.00% (421,344B) 0x10DBA0: cmd_select (console.c:601) | | | ->43.00% (421,344B) 0x10DE6D: run_console (console.c:674) | | | ->43.00% (421,344B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->36.71% (359,702B) 0x10E399: q_insert_head (queue.c:64) | | ->36.71% (359,702B) 0x10EAA3: measure (constant.c:76) | | | ->36.71% (359,702B) 0x10EB7E: doit (fixture.c:136) | | | ->36.71% (359,702B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->36.71% (359,702B) 0x10AE1A: do_size (qtest.c:482) | | | ->36.71% (359,702B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->36.71% (359,702B) 0x10D338: interpret_cmd (console.c:247) | | | ->36.71% (359,702B) 0x10DBA0: cmd_select (console.c:601) | | | ->36.71% (359,702B) 0x10DE6D: run_console (console.c:674) | | | ->36.71% (359,702B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->00.01% (64B) in 1+ places, all below ms_print's threshold (01.00%) | ->01.67% (16,347B) in 12 places, all below massif's threshold (1.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 45 22,410,582,233 691,504 564,228 127,276 0 46 22,906,285,509 575,408 470,207 105,201 0 47 23,567,223,065 102,120 85,737 16,383 0 48 24,228,160,705 47,848 41,635 6,213 0 49 24,558,629,618 413,360 338,365 74,995 0 50 24,852,151,295 309,352 253,855 55,497 0 51 25,145,673,018 803,944 655,724 148,220 0 52 25,439,194,714 441,576 361,213 80,363 0 53 25,732,716,420 338,920 277,857 61,063 0 54 26,026,238,269 375,984 308,165 67,819 0 81.96% (308,165B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->77.61% (291,818B) 0x10DEDF: test_malloc (harness.c:138) | ->41.81% (157,192B) 0x10E375: q_insert_head (queue.c:59) | | ->41.81% (157,192B) 0x10EAA3: measure (constant.c:76) | | | ->41.81% (157,192B) 0x10EB7E: doit (fixture.c:136) | | | ->41.81% (157,192B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->41.81% (157,192B) 0x10AE1A: do_size (qtest.c:482) | | | ->41.81% (157,192B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->41.81% (157,192B) 0x10D338: interpret_cmd (console.c:247) | | | ->41.81% (157,192B) 0x10DBA0: cmd_select (console.c:601) | | | ->41.81% (157,192B) 0x10DE6D: run_console (console.c:674) | | | ->41.81% (157,192B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->35.79% (134,562B) 0x10E399: q_insert_head (queue.c:64) | | ->35.79% (134,562B) 0x10EAA3: measure (constant.c:76) | | | ->35.79% (134,562B) 0x10EB7E: doit (fixture.c:136) | | | ->35.79% (134,562B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->35.79% (134,562B) 0x10AE1A: do_size (qtest.c:482) | | | ->35.79% (134,562B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->35.79% (134,562B) 0x10D338: interpret_cmd (console.c:247) | | | ->35.79% (134,562B) 0x10DBA0: cmd_select (console.c:601) | | | ->35.79% (134,562B) 0x10DE6D: run_console (console.c:674) | | | ->35.79% (134,562B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->00.02% (64B) in 1+ places, all below ms_print's threshold (01.00%) | ->02.42% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->02.19% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->02.19% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->02.19% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.23% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->01.93% (7,251B) in 11 places, all below massif's threshold (1.00%) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 55 26,319,760,052 627,304 512,013 115,291 0 56 26,613,281,750 87,728 74,028 13,700 0 57 26,906,803,465 106,856 89,523 17,333 0 58 27,200,325,223 553,392 452,071 101,321 0 59 27,493,846,934 201,704 166,547 35,157 0 60 27,787,368,701 697,960 569,144 128,816 0 61 28,080,890,458 595,944 486,374 109,570 0 62 28,374,412,178 895,280 729,489 165,791 0 63 28,667,933,895 219,368 180,804 38,564 0 64 28,961,455,583 521,904 426,399 95,505 0 81.70% (426,399B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->78.57% (410,052B) 0x10DEDF: test_malloc (harness.c:138) | ->42.35% (221,032B) 0x10E375: q_insert_head (queue.c:59) | | ->42.35% (221,032B) 0x10EAA3: measure (constant.c:76) | | | ->42.35% (221,032B) 0x10EB7E: doit (fixture.c:136) | | | ->42.35% (221,032B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->42.35% (221,032B) 0x10AE1A: do_size (qtest.c:482) | | | ->42.35% (221,032B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->42.35% (221,032B) 0x10D338: interpret_cmd (console.c:247) | | | ->42.35% (221,032B) 0x10DBA0: cmd_select (console.c:601) | | | ->42.35% (221,032B) 0x10DE6D: run_console (console.c:674) | | | ->42.35% (221,032B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->36.21% (188,956B) 0x10E399: q_insert_head (queue.c:64) | | ->36.21% (188,956B) 0x10EAA3: measure (constant.c:76) | | | ->36.21% (188,956B) 0x10EB7E: doit (fixture.c:136) | | | ->36.21% (188,956B) 0x10EEB7: is_size_const (fixture.c:188) | | | ->36.21% (188,956B) 0x10AE1A: do_size (qtest.c:482) | | | ->36.21% (188,956B) 0x10CEA1: interpret_cmda (console.c:224) | | | ->36.21% (188,956B) 0x10D338: interpret_cmd (console.c:247) | | | ->36.21% (188,956B) 0x10DBA0: cmd_select (console.c:601) | | | ->36.21% (188,956B) 0x10DE6D: run_console (console.c:674) | | | ->36.21% (188,956B) 0x10C2D1: main (qtest.c:789) | | | | | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%) | | | ->00.01% (64B) in 1+ places, all below ms_print's threshold (01.00%) | ->01.74% (9,096B) 0x10C946: malloc_or_fail (report.c:189) | ->01.57% (8,216B) 0x10CFF9: push_file (console.c:457) | | ->01.57% (8,216B) 0x10DDDE: run_console (console.c:659) | | ->01.57% (8,216B) 0x10C2D1: main (qtest.c:789) | | | ->00.17% (880B) in 1+ places, all below ms_print's threshold (01.00%) | ->01.39% (7,251B) in 11 places, all below massif's threshold (1.00%) ``` ## web server 實作 - web-server 引用自 [tiny-web_server](https://github.com/7890/tiny-web-server) - 修正裡面使用 sprintf 的實作,改用 snprintf ,對於長度過長不會發生溢位。 - 修正 local variable 的 scope ,不需要宣告在較大的 scope 中。 - 新增 web 指令在 qtest 中,可以開啟 web server ```cpp add_cmd("web", do_open_web, " | run a webserver"); ``` - 新增 closeweb 指令在 qtest 中,可以關閉 web-server ```cpp add_cmd("closeweb", do_close_web, " | close webserver"); ``` - 若沒手動關閉 web server ,程式也會在 quit 後,自動關閉 web server - 目前為了讓 web server 可以在 qtest 的背景執行,使用 fork 實作,之後會改成 coroutine

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully