# 2018q3 Homework2 (lab0) contributed by < [`yanjiunhaha`](https://github.com/yanjiunhaha) > ###### tags: `lab note` [==作業題目==](https://hackmd.io/s/BJp_jq-tm) #### 代辦事項: - [ ] harness.c 它把我們的 `malloc()` 和 `free()` 取代成自己實做的 `test_malloc()` 和 `test_free()`。 有必要查清楚它做了什麼。 - [x] `strdup()`, `strcpy()`, `strncpy()` 差異,以及實做內容。 - [ ] scripts/driver.py 了解自動化測試程式概念。 寫程式測試程式!? ~~帥沒有第二個字可以形容。~~ - [ ] install-git-hooks 第一次使用 git-hooks 。 本以為它會自動檢查++撰寫程式風格++而已。 後來發現它可以做更多檢查功能!? ~~跟上面一樣帥。~~ 該檢查一下設定檔做了哪些事情了。 --- ## [Makefile](https://github.com/sysprog21/lab0-c/blob/master/Makefile) ###### Resource : [How to read makefile](https://hackmd.io/c/rJKbX1pFZ/https%3A%2F%2Fhackmd.io%2Fs%2FSySTMXPvl) 我習慣在剛開始接觸一支程式時,先了解大致的程式結構。 * 主要功能與==目的== * 要達到==目的==所需的==模組==。 * 了解檔案的擺放==位置==與檔案之間的==連結==關係。 在我開始接觸 **Linux** 之後,我認識了 **GUN make** 。 這是一個非常好的東西,它可以完成許多自動化工作。 最重要的是它的檔案 ==**Makefile**== ,我們可以很輕鬆的透過觀察這個檔案來了解整支程式的檔案架構。 如果開發人員習慣很好,就可以從這些檔案之間的關係,找出程式使用了哪些**模組**。 寫程式的人都知道,大部分最浪費時間的工作就是**了解別人的程式碼**。我們可以透過 ==Makefile== 來加速這個過程,並且可以有效減少錯誤。 > 我寫程式的習慣很差,這是我很需要學習的地方。[name=YanJiun][time=Sat, Sep 22, 2018 12:19 PM] --- * 首先先觀察 Makefile 的參數設定。 ```= cc = gcc cflag = -O0 -g -wall -werror git_hooks := .git/hooks/applied ``` * #1 這裡編譯器使用 `gcc`。 順代一提 `cc` 是 **Uinx** 編譯器名稱的慣例 在 **Linux** 中為了讓 **Uinx** 程式方便移植,因此在 **Linux** 使用 `cc` 會直接指到 `gcc` 。 * #2 這裡是設定給 `gcc` 的參數。 `-O` 最佳化參數: `-O0` 表示沒有優化, `-O1` 為預設值,`-O3` 最高等級優化 `-g` 加入除錯資訊。否則使用 `gdb` 進行偵錯時,會看不到所有函式名稱。 `-Wall` 顯示所有警告訊息。會顯示編寫程式碼建議。每次使用 `gcc` 都要加入此參數。 `-Werror` 視告為錯誤,出現任何警告都會停止編譯。 :::success function 在數學用語翻譯為「函數」,但在程式語言中一般翻譯為「函式」 :notes: jserv ::: > 了解了。以後會注意用字的精準度。[name=YanJiun][time=Sun, Sep 23, 2018 4:13 PM] * 檔案的相依性 (只提一下觀察順序,詳細請自行參考 [Makefile](https://github.com/sysprog21/lab0-c/blob/master/Makefile)) * `$ make` 1. all $\Rightarrow$ $(GIT_HOOKS) qtest 2. $(GIT_HOOKS) 3. qtest $\Rightarrow$ queue.o * 補充:`#6` 和 `#17` 的 `tar cf handin.tar queue.h queue.c` 可以註解(`#`)掉,猜測是 **CMU** 要讓學生教作業用的? :::info 請 `git rebase`,在 [lab0-c](https://github.com/sysprog21/lab0-c) 已調整。參見 [Git - 更新 fork 出來的 repository](https://dotblogs.com.tw/explooosion/2018/08/09/025208) :notes: jserv ::: * 還有另外兩的自動化功能 * `$ make test` 自動化測試,這是本次我最有興趣的地方。 往後我會詳細閱讀 `script/driver.py` 內容,加以分享。 * `$ make clean` 清除 make 產生檔案。 --- ## [glibc/string](https://github.com/lattera/glibc/tree/master/string) ### [strdup.c](https://github.com/lattera/glibc/blob/master/string/strdup.c) 先說結論:++本次作業無法使用此函式,否則滿分只是假象。++ ```c= char * __strdup (const char *s) { size_t len = strlen (s) + 1; void *new = malloc (len); if (new == NULL) return NULL; return (char *) memcpy (new, s, len); } ``` 這個函式有用到 `malloc()` ,因此它回傳的指標使用完需要 `free()` 。 ==但 `harness.h` #58,59 將 `malloc()` 和 `free()` 兩函式都取代成自己實現的函式。== 因此這裡使用 `free()` 釋放 `strdup()` 回傳的指標會錯誤。因為你用的 `free()` 其實是 `test_free()`。 - 延伸思考 這裡也許可以在 `#include<string.h>` 之前,就先 `#include<harness.h>`。 讓++前置處理器++將 `string` 中的 `malloc()` 也取代成我們的 `test_malloc()`。 - 但`harness.h` 中也有使用到 `string.h`,因此需要將所用到的函式都自己實做。 - 由於 glibc 程式碼非常多,因此就算解決上述問題。我也無法確定是否真的可以取代 `string` 裡的 `malloc()`,不知道是否會有許多衍生問題。 延伸閱讀:[memcpy](https://github.com/lattera/glibc/blob/master/string/memcpy.c) , [strlen](https://github.com/lattera/glibc/blob/master/string/strlen.c) - 補充心得 我實做時的 `strlen()` 是自己實做的。 但我看到 `strlen.c` 時才發現這件事其實沒有這麼簡單。 --- ### [strcpy.c](https://github.com/lattera/glibc/blob/master/string/strcpy.c) / [strncpy.c](https://github.com/lattera/glibc/blob/master/string/strncpy.c) 基本上沒什麼好說的。值得一提的是要複製的目的位址要先用 `malloc()` 配置好空間。 #### strcpy ```c= char * STRCPY (char *dest, const char *src) { return memcpy (dest, src, strlen (src) + 1); } ``` #### strncpy ```c= char * STRNCPY (char *s1, const char *s2, size_t n) { size_t size = __strnlen (s2, n); if (size != n) memset (s1 + size, '\0', n - size); return memcpy (s1, s2, size); } ``` 延伸閱讀:[memset](https://github.com/lattera/glibc/blob/master/string/memset.c) , [memcpy](https://github.com/lattera/glibc/blob/master/string/memcpy.c) --- ## harness ### setjmp #### resource [C 語言 setjmp 與 longjmp 函數用法教學](https://blog.gtwang.org/programming/c-setjmp-longjmp-function-tutorial/) [C語言: 認識關鍵字volatile](http://newscienceview.blogspot.com/2013/09/c-volatile.html) [C 库函数 - signal()](http://www.runoob.com/cprogramming/c-function-signal.html) --- ## 實驗環境 ``` yanjiun@yanjiun-X550VX:~$ cat /etc/os-release NAME="Ubuntu" VERSION="18.04.1 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.1 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic yanjiun@yanjiun-X550VX:~$ cat /proc/version Linux version 4.15.0-34-generic (buildd@lgw01-amd64-047) (gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)) #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 ``` --- ## 實驗結果 ``` ... ... +++ 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 ```