楊鴻志
    • 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
    # 2018q3 Homework2(lab0) contributed by <[`datuiji`](https://github.com/datuiji/lab0-c)> ## 實驗環境 ```clike= NAME="Ubuntu" VERSION="16.04.5 LTS (Xenial Xerus)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 16.04.5 LTS" VERSION_ID="16.04" HOME_URL="http://www.ubuntu.com/" SUPPORT_URL="http://help.ubuntu.com/" BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/" VERSION_CODENAME=xenial UBUNTU_CODENAME=xenial ``` ## 實驗結果 ```clike= --- Trace Points +++ TESTING trace trace-01-ops: # Test of insert_head and remove_head --- trace-01-ops 6/6 +++ TESTING trace trace-02-ops: # Test of insert_head, insert_tail, and remove_head --- trace-02-ops 6/6 +++ TESTING trace trace-03-ops: # Test of insert_head, insert_tail, reverse, and remove_head --- trace-03-ops 6/6 +++ TESTING trace trace-04-ops: # Test of insert_head, insert_tail, and size --- trace-04-ops 6/6 +++ TESTING trace trace-05-ops: # Test of insert_head, insert_tail, remove_head reverse, and size --- trace-05-ops 6/6 +++ TESTING trace trace-06-string: # Test of truncated strings --- trace-06-string 7/7 +++ TESTING trace trace-07-robust: # Test operations on NULL queue --- trace-07-robust 7/7 +++ TESTING trace trace-08-robust: # Test operations on empty queue --- trace-08-robust 7/7 +++ TESTING trace trace-09-robust: # Test remove_head with NULL argument --- trace-09-robust 7/7 +++ TESTING trace trace-10-malloc: # Test of malloc failure on new --- trace-10-malloc 7/7 +++ TESTING trace trace-11-malloc: # Test of malloc failure on insert_head --- trace-11-malloc 7/7 +++ TESTING trace trace-12-malloc: # Test of malloc failure on insert_tail --- trace-12-malloc 7/7 +++ TESTING trace trace-13-perf: # Test performance of insert_tail --- trace-13-perf 7/7 +++ TESTING trace trace-14-perf: # Test performance of size --- trace-14-perf 7/7 +++ TESTING trace trace-15-perf: # Test performance of insert_tail, size, and reverse --- trace-15-perf 7/7 --- TOTAL 100/100 ``` ## 開發紀錄 ### queue.h ```clike= /* Queue structure */ typedef struct { list_ele_t *head; /* Linked list of elements */ list_ele_t *tail; int size; /* You will need to add more fields to this structure to efficiently implement q_size and q_insert_tail */ } queue_t; ``` - 在queue.h中,新增了 tail 指標與 int size,新增 tail 指標原因是為了紀錄 queue 的 tail ,如此才能實做 bool q_queue_tail(queue_t *q,char *s) 在 O(1) 時間內,而新增 int size 是因為能夠實做 int q_size(queue_t *q) 在 O(1) 時間內。 ### queue_t *q_new() ```clike= queue_t *q_new() { queue_t *q = malloc(sizeof(queue_t)); /* What if malloc returned NULL? */ if (q == NULL) { return NULL; } else { q->head = NULL; q->tail = NULL; q->size = 0; return q; } } ``` - 此處因為做了 malloc 所以必須考慮到 malloc 是否成功,如果失敗則回傳 NULL 。 ### q_free() ```clike= void q_free(queue_t *q) { /* How about freeing the list elements and the strings? */ if (q == NULL) { return; } else { while (q->head) { list_ele_t *temp = q->head; free(temp->value); q->head = q->head->next; free(temp); } } ``` - 在這個函式中,功能為刪除整個 queue ,所以需要拜訪完整個 queue 並 free 節點與它的數值。 ### bool q_insert_head(queue_t *q, char *s) ```clike= bool q_insert_head(queue_t *q, char *s) { /* What should you do if the q is NULL? */ if (q == NULL) { return false; } else { /* Don't forget to allocate space for the string and copy it */ /* What if either call to malloc returns NULL? */ list_ele_t *newh; newh = malloc(sizeof(list_ele_t)); if (newh == NULL) { return false; } else { newh->value = malloc(sizeof(char) * (strlen(s) + 1)); if (newh->value == NULL) { free(newh); return false; } strcpy(newh->value, s); if (q->head == NULL) { q->head = newh; q->tail = newh; newh->next = NULL; } else { newh->next = q->head; q->head = newh; } q->size++; return true; } } } ``` - 實作邏輯為: - 先 malloc 記憶體給欲插入節點的數值,之後判斷 malloc 是否成功,再來將新節點的數值 s 複製給剛 malloc 的記憶體空間,之後移動指標,如果插入 queue 還沒有節點,就把新節點設為 head 與 tail 否則將新節點加入 queue 中,並移動指標。 - 在處理這函式的時候一開使用的是 strdup 。 ```clike= bool q_insert_head(queue_t *q, char *s) { /* What should you do if the q is NULL? */ if(q == NULL){ return false; } else{ /* Don't forget to allocate space for the string and copy it */ /* What if either call to malloc returns NULL? */ list_ele_t *newh; newh = malloc(sizeof(list_ele_t)); if(newh == NULL){ return false; } else{ newh->value = strdup(s); if(q->head == NULL){ q->head = newh; q->tail = newh; newh->next = NULL; } else{ newh->next = q->head; q->head = newh; } q->size++; return true; } } } ``` - 導致以下錯誤: ```clike= +++ TESTING trace trace-01-ops: # Test of insert_head and remove_head ERROR: Attempted to free unallocated block. Address = 0xc56500 ERROR: Attempted to free unallocated or corrupted block. Address = 0xc56500 ERROR: Segmentation fault occurred. You dereferenced a NULL or invalid pointer ERROR: Removal from queue failed (1 failures total) ERROR: Attempted to free unallocated block. Address = 0xc56520 ERROR: Attempted to free unallocated or corrupted block. Address = 0xc56520 ERROR: Corruption detected in block with address 0xc56520 when attempting to free it ERROR: Segmentation fault occurred. You dereferenced a NULL or invalid pointer ERROR: Removal from queue failed (2 failures total) ERROR: Attempted to free unallocated block. Address = 0xc56560 ERROR: Attempted to free unallocated or corrupted block. Address = 0xc56560 ERROR: Corruption detected in block with address 0xc56560 when attempting to free it ERROR: Segmentation fault occurred. You dereferenced a NULL or invalid pointer ERROR: Removal from queue failed (3 failures total) --- trace-01-ops 0/6 ``` - 在函式中用了 strdup 所以 free 時造成以上錯誤,這邊不能使用 strdup 原因是因為原本使用 strdup 是用了原本 c 語言定義的 malloc 與 free,而在這個 harness.h 中已經把 malloc 重新定義為 *test_malloc 而 free 重新定義為 test_free 。 ### bool q_insert_tail(queue_t *q, char *s) ```clike= bool q_insert_tail(queue_t *q, char *s) { /* You need to write the complete code for this function */ /* Remember: It should operate in O(1) time */ if (q == NULL) { return false; } else { list_ele_t *newh; newh = malloc(sizeof(list_ele_t)); if (newh == NULL) { return false; } else { newh->value = malloc(sizeof(char) * (strlen(s) + 1)); if (newh->value == NULL) { free(newh); return false; } strcpy(newh->value, s); if (q->head == NULL) { q->head = newh; q->tail = newh; newh->next = NULL; } else { q->tail->next = newh; q->tail = newh; newh->next = NULL; } q->size++; return true; } } } ``` - 在實作 insert_tail 這個函式沒什麼問題,因為邏輯跟insert_head差不多。 ### bool q_remove_head(queue_t *q, char *sp, size_t bufsize) ```clike= bool q_remove_head(queue_t *q, char *sp, size_t bufsize) { /* You need to fix up this code. */ if (q == NULL || q->size == 0) { return false; } else { list_ele_t *temp = q->head; q->head = q->head->next; if (sp != NULL) { memset(sp, '\0', bufsize); strncpy(sp, temp->value, bufsize - 1); } free(temp->value); free(temp); q->size--; if (q->size == 0) { q->tail = NULL; } return true; } } ``` - 實作邏輯為:先判斷 queue 是否有節點,如果沒有節點做 remove head 就會回傳失敗,否則先宣告一個暫存節點,把欲刪除節點的數值存到 sp 中,之後陸續把欲刪除節點之數值與節點本身 free 掉。 - 在實作 remove head 時,我一開始用了下列方法: ```clike= bool q_remove_head(queue_t *q, char *sp, size_t bufsize) { /* You need to fix up this code. */ if(q == NULL || q->size == 0){ return false; } else{ list_ele_t *temp = q->head; if(temp->value != NULL){ strncpy(sp, temp->value, bufsize); free(temp->value); } q->head = q->head->next; free(temp); q->size--; if(q->size == 0){ q->tail = NULL; } return true; } } ``` - 造成以下錯誤: ```clike= +++ TESTING trace trace-06-string: # Test of truncated strings ERROR: Removed value meerkat_panda_squirrel_vulture_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX != expected value meerkat_panda_squirrel_vulture ERROR: Removed value aardvark_bear_dolphin_gerbil_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX != expected value aardvark_bear_dolphin_gerbil ERROR: Removed value aardvark_bear_dolphin_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX != expected value aardvark_bear_dolphin ERROR: Removed value meerkat_panda_squirrel_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX != expected value meerkat_panda_squirrel ERROR: Removed value meerkat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX != expected value meerkat Error limit exceeded. Stopping command execution --- trace-06-string 0/7 ``` - 後來找到在 if(temp->value != NULL) 這個判斷時出錯,因為改用 if (sp != NULL) 邏輯才合理,且以下動作改成 memset 先初始化 sp 為 '\0' 然後在用 strncpy 將節點數值複製到 sp ,最後把節點數值跟節點本身 free 掉,這樣就成功了。 ### int q_size(queue_t *q) ```clike= int q_size(queue_t *q) { /* You need to write the code for this function */ /* Remember: It should operate in O(1) time */ if (q == NULL) { return 0; } else { return q->size; } } ``` - 因為在前面的函式中都有紀錄 q->size 所以在此函式中就只需要回傳 q->size。 ### void q_reverse(queue_t *q) ```clike= void q_reverse(queue_t *q) { /* You need to write the code for this function */ if (q == NULL || q->size == 0) { return; } list_ele_t *pre = NULL; list_ele_t *cur = q->head; list_ele_t *next = NULL; while (cur != NULL) { next = cur->next; cur->next = pre; pre = cur; cur = next; } q->tail = q->head; q->head = pre; return; } ``` - 實作 reverse 我用了三個指標來達到此目的,並參考此篇作法:https://www.youtube.com/watch?v=oVd1uAZ6Q4U&ab_channel=%E9%99%B3%E9%8C%A6%E8%BC%9D 。 ## 自動評分系統運作的原理 - [Makefile 參考資料](http://mropengate.blogspot.com/2018/01/makefile.html) - Makefile ```clike= CC = gcc CFLAGS = -O0 -g -Wall -Werror GIT_HOOKS := .git/hooks/applied all: $(GIT_HOOKS) qtest $(GIT_HOOKS): @scripts/install-git-hooks @echo queue.o: queue.c queue.h harness.h $(CC) $(CFLAGS) -c queue.c qtest: qtest.c report.c console.c harness.c queue.o $(CC) $(CFLAGS) -o qtest qtest.c report.c console.c harness.c queue.o test: qtest scripts/driver.py scripts/driver.py clean: rm -f *.o *~ qtest rm -rf *.dSYM (cd traces; rm -f *~) ``` - 在 Makefile 中發現當執行 make test 時會執行 scripts/driver.py 所以只要知道 driver.py 的功能就知道自動評分系統如何運作。 - driver.py ```clike= #!/usr/bin/python import subprocess import sys import getopt # Driver program for C programming exercise class Tracer: traceDirectory = "./traces" qtest = "./qtest" verbLevel = 0 autograde = False traceDict = { 1 : "trace-01-ops", 2 : "trace-02-ops", 3 : "trace-03-ops", 4 : "trace-04-ops", 5 : "trace-05-ops", 6 : "trace-06-string", 7 : "trace-07-robust", 8 : "trace-08-robust", 9 : "trace-09-robust", 10 : "trace-10-malloc", 11 : "trace-11-malloc", 12 : "trace-12-malloc", 13 : "trace-13-perf", 14 : "trace-14-perf", 15 : "trace-15-perf" } traceProbs = { 1 : "Trace-01", 2 : "Trace-02", 3 : "Trace-03", 4 : "Trace-04", 5 : "Trace-05", 6 : "Trace-06", 7 : "Trace-07", 8 : "Trace-08", 9 : "Trace-09", 10 : "Trace-10", 11 : "Trace-11", 12 : "Trace-12", 13 : "Trace-13", 14 : "Trace-14", 15 : "Trace-15" } maxScores = [0, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7] def __init__(self, qtest = "", verbLevel = 0, autograde = False): if qtest != "": self.qtest = qtest self.verbLevel = verbLevel self.autograde = autograde def runTrace(self, tid): if not tid in self.traceDict: print("ERROR: No trace with id %d" % tid) return False fname = "%s/%s.cmd" % (self.traceDirectory, self.traceDict[tid]) vname = "%d" % self.verbLevel clist = [self.qtest, "-v", vname, "-f", fname] try: retcode = subprocess.call(clist) except Exception as e: print("Call of '%s' failed: %s" % (" ".join(clist), e)) return False return retcode == 0 def run(self, tid = 0): scoreDict = { k : 0 for k in self.traceDict.keys() } print("---\tTrace\t\tPoints") if tid == 0: tidList = self.traceDict.keys() else: if not tid in self.traceDict: print("ERROR: Invalid trace ID %d" % tid) return tidList = [tid] score = 0 maxscore = 0 for t in tidList: tname = self.traceDict[t] if self.verbLevel > 0: print("+++ TESTING trace %s:" % tname) ok = self.runTrace(t) maxval = self.maxScores[t] tval = maxval if ok else 0 print("---\t%s\t%d/%d" % (tname, tval, maxval)) score += tval maxscore += maxval scoreDict[t] = tval print("---\tTOTAL\t\t%d/%d" % (score, maxscore)) if self.autograde: # Generate JSON string jstring = '{"scores": {' first = True for k in scoreDict.keys(): if not first: jstring += ', ' first = False jstring += '"%s" : %d' % (self.traceProbs[k], scoreDict[k]) jstring += '}}' print(jstring) def usage(name): print("Usage: %s [-h] [-p PROG] [-t TID] [-v VLEVEL]" % name) print(" -h Print this message") print(" -p PROG Program to test") print(" -t TID Trace ID to test") print(" -v VLEVEL Set verbosity level (0-3)") sys.exit(0) def run(name, args): prog = "" tid = 0 vlevel = 1 levelFixed = False autograde = False optlist, args = getopt.getopt(args, 'hp:t:v:A') for (opt, val) in optlist: if opt == '-h': usage(name) elif opt == '-p': prog = val elif opt == '-t': tid = int(val) elif opt == '-v': vlevel = int(val) levelFixed = True elif opt == '-A': autograde = True else: print("Unrecognized option '%s'" % opt) usage(name) if not levelFixed and autograde: vlevel = 0 t = Tracer(qtest = prog, verbLevel = vlevel, autograde = autograde) t.run(tid) if __name__ == "__main__": run(sys.argv[0], sys.argv[1:]) ``` - 當在 command line 輸入 make test 就會開始執行 run 函式執行自動測試,另外還有一個功能就是可以獨立測試15個 trace 。 ## qtest 的行為和裡頭的技巧 - 當我們輸入 ./qtest 時,command line 會出現 cmd ,此時就可以開始輸入測資開始測試,所以我很好奇這項功能如何工作。打開 qtest.c 可以看見 static void console_init() 這個函式主要是讓我們能輸入測資進行測試,但在 qtest.c 中我找不到 add_cmd 的函式,於是我 google 一下發現這是運用 GDB 的技巧,透過此項功能可以讓我們更容易去除錯。 ```clike= 2.5. Adding Commands to GDB As noted in Section 2.2, GDB's command handling is extensible. Commands are grouped into a number of command lists (of type struct cmd_list_element), pointed to by a number of global variables (defined in cli-cmds.h). Of these, cmdlist is the list of all defined commands, with separate lists defined for sub-commands of various top level commands. For example infolist is the list of all info sub-commands. Each command (or sub-command) is associated with a callback function which implements the behavior of the functions. There are additional requirements for functions which set or show values within GDB. Each function also takes a documentation string (used by the help command). Functions for adding commands all return a pointer to the struct cmd_list_element for the command added (which is not necessarily the head of its command list). The most useful functions are: add_cmd. Add a function to a command list. add_com. Add a function to the main command list, cmdlist. This is a convenience wrapper for add_cmd. add_prefix_cmd. Add a new prefix command. This command should have its own function for use if it is called on its own, and a global command list pointer specific to the prefix command to which all its sub-commands will be added. If a prefix command is called with an unknown sub-command, it can either give an error or call the function of the prefix command itself. Which of these is used is specified by a flag in the call to add_prefix_cmd. add_alias_cmd. Add an alias for a command already defined. add_info. Add a sub-command to the info. A convenience wrapper for add_cmd. New commands are usually added in the _initialize_arch function after the struct gdbarch has been defined. ``` ```clike= static void console_init() { add_cmd("new", do_new, " | Create new queue"); add_cmd("free", do_free, " | Delete queue"); add_cmd("ih", do_insert_head, " str [n] | Insert string str at head of queue n times " "(default: n == 1)"); add_cmd("it", do_insert_tail, " str [n] | Insert string str at tail of queue n times " "(default: n == 1)"); add_cmd("rh", do_remove_head, " [str] | Remove from head of queue. Optionally compare " "to expected value str"); add_cmd( "rhq", do_remove_head_quiet, " | Remove from head of queue without reporting value."); add_cmd("reverse", do_reverse, " | Reverse queue"); add_cmd("size", do_size, " [n] | Compute queue size n times (default: n == 1)"); add_cmd("show", do_show, " | Show queue contents"); add_param("length", &string_length, "Maximum length of displayed string", NULL); add_param("malloc", &fail_probability, "Malloc failure probability percent", NULL); add_param("fail", &fail_limit, "Number of times allow queue operations to return false", NULL); } ``` ## 參考資料 - [GNU debugger](https://www.embecosm.com/appnotes/ean3/embecosm-howto-gdb-porting-ean3-issue-2.html)

    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