# 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
```