\0
?linux2020
lab0-c
Q&A
in Linux man page:
Warning: If there is no null byte among the first n bytes of src, the string placed
in dest will not be null-terminated.
前言:
觀察許多同學在撰寫 lab0-c q_insert_head()
時,都會使用
strncpy 來複製要寫入 head->value
的字串
但如果我們在傳入參數給 strncpy
時把 len
改成 len+1
的話,或許我們就不需要額外手動幫 str
這個字串補上 \0
了
為了驗證這個猜測,我做了以下實驗,
並分成兩種狀況討論:
參照 man page 的 strncpy
simple implementation
寫出一個函式 mystrncpy()
我們發現 第一個 for-loop 的結束條件是 i == n
或 src[i] == '\0'
設計實驗:
我們把 dest 指向的記憶體空間設置成 'A'
,只所以多把不屬於 dest的 2 個 byte 也設置成 'A'
的原因是,
不知道為什麼,malloc()出來的記憶體空間的數值都是 0x00
為了避免影響到實驗結果,所以把 dest 指向的記憶體空間後面 2 個 byte 也設置成 'A'
確認何時迴圈會停止
n == 5
因為我們設定 copy 的字元數 n == 5
的關係,所以在 copy 完 o
之後,就跳出 for 迴圈並回傳 dest
結論:
如果把 strncpy 的 argument n 指定成 len,也就是不從 src
複製 \0
的話,strncpy 就不會自動幫你補上 \0
,導致出現錯誤。
對於 man page 理解有誤
把 mystrncpy 的 字串長度 argument 設定成 len + 1
在
確認一下 str 指向的記憶體內部的數值
發現都是 0,
murmur: malloc 不是不會初始化分配到的記憶體區塊嗎?
unknowntpoMon, Apr 20, 2020 7:18 AM
把 dest
指向的 6 個 byte 都設成 'A'
來觀察strncpy是否 會自動補上 \0
接下來,尋找在 i
為多少時會跳入下一個 for-loop 並被補上 \0
我們發現在 i == 5
時,因為 src[i] == '\0'
,所以觸發第一個迴圈的終止條件,於是跳入下一個迴圈,
結論:
如果在 strncpy 傳入的字元個數為 len + 1
,
那 strncpy 就會自動幫你補上 \0
in Linux man page STRCPY(3)
If the length of src is less than n, strncpy() writes additional null bytes to dest to ensure that a total of n bytes are written.
應該理解成
如果 src 的長度小於 n,strncpy()
會多寫入足夠的\0
到 dest 來確保一共有 n 個 bytes 都被寫入 dest。
所以原本
可以改成
strncpy的參數size_t n,我個人認為用來限制dest的size,而不是描述src的length。
筆記中的 "len+1 means we want to copy\0
from src",這是錯誤理解,strncpy是指最多copy n個,如果copy小於n個,會幫你補上null byte,請看man page:
'''Man page: "If the length of src is less than n, strncpy() writes additional null bytes to dest to ensure that a total of n bytes are written.'''
原文是寫write additional,而不是copy from src。
請考慮src的實際長度大於n時,你原本的描述是否仍成立。
參考資料
c-faq:Why does strncpy not always place a '\0' terminator in the destination string?
實務上比較常看到
寫法1:
dst = strdup(src); //return的結果一樣要記得檢查
寫法2:
size=strlen(src)+1;
ds = malloc(size); //or use calloc(…)
strncpy(dst, src, size);
陳東怡
https://github.com/keith-packard/picolibc/blob/master/newlib/libc/string/strncpy
張辰謙
, 你對照閱讀 man page 和查看 PicoLibc/Newlib 關於 strncpy 函式的實作程式碼,以釐清自己 語文認知 的問題在哪裡
jserv老師
在 lab0-c q_insert_head()
中
為什麼在做完 string copy, 並 return 之前,我嘗試釋放一個自己 malloc 的記憶體區塊 str 時,反而在使用make test
測試的時候產生亂碼並出現錯誤訊息呢?
FB 問答回覆
在
q_insert head()
中的 91 行,將 newh->value = str 時 newh->value 跟 str 指向同一個地方,當 free(str) 會讓
newh->value 指向一個空的地方。
還有在 q_insert_head 中 85 行 strncpy 執行完後可以不用 str[len] = '\0'; ,strncpy 會幫你填 '\0'。
張佳鴻
我的解讀
為了從 s 複製一個字串的內容而動態配置的記憶體片段,原本是由 str 指向它 , 但是經由 newh->value = str 這個動作,現在換成是 newh->value 與str 來指向它並存在 linked list 內,所以並不需要釋放這個記憶體片段
老師補充
感謝 張佳鴻 回覆。注意 Linux Programmer's Manual 的說明: "If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated." / "If the length of src is less than n, strncpy() writes additional null bytes to dest to ensure that a total of n bytes are written."
我查的資料
in Linux Programmer's Manual
"The stpncpy() and strncpy() functions copy at most len characters from
src into dst. If src is less than len characters long, the remainder of
dst is filled with\0'
characters. Otherwise, dst >is not terminated.
The source and destination strings should not >overlap, as the behavior is
undefined."