我可以指出你的男人網頁,網站等,但最終重要的是C標準本身。作爲標準運行時庫的一部分,使用和行爲在C99-§7.23.2.4定義爲:
#include <string.h>
char *strncpy(char * restrict s1,
const char * restrict s2,
size_t n);
說明 的strncpy
功能拷貝不超過n個字符(即遵循一個字符空字符不會被複制)從s2指向的數組轉到 s1指向的數組。如果在重疊對象之間進行復制,則行爲不確定。 如果s2指向的數組的長度小於n個字符,則在s1指向的數組副本中會添加空字符,直到寫入全部n個字符爲止。
返回 strncpy
函數返回s1的值。
有顯著隱含的信息在這裏,最重要的是:strncpy()
將不以空字符終止您的目標字符串,如果源字符串長度(不包括其空字符終止)達到或超過指定的目標緩衝區長度)。
此外,雖然在標準中明確規定(見上文),它繼續混淆了我很多的工程師怎麼都沒有意識到,strncpy()
尾填充空字符到指定的長度n
目標字符串緩衝區到達時源字符串長度爲,比目標緩衝區大小小。這得出了以下不可避免的結論:
strncpy()
API將始終將n
字符寫入目標緩衝區引用的地址。
在你的情況,因爲目標緩衝區只有10字符寬,你寫90個其他字符過去寫存儲器的定義高端,因此走進的未定義行爲土地。
在這一點上,你必須問自己:「那麼最新的使用?」有是一個可以說是最基本的用例。它允許你複製最多n
字符到目標緩衝區,並且知道你不會超過n
字符。期。不過說到底,你想有一個空值終止字符串,因此的正確用法是這樣的:
char dst[ N ];
strncpy(dst, src, N-1);
dst[N-1] = 0;
其中N
是dst
緩衝區的硬長度字符,是大於,或相等到1
。需要注意的是dst
可能只是-AS-不失爲一個動態分配的內存指針:
char *dst = malloc(N * sizeof(char));
strncpy(dst, src, N-1);
dst[N-1] = 0;
通過上述,您將總是必須在dst
一個空結尾的字符串。如果源字符串長度爲小於指定的目標緩衝區長度,則strncpy()
將用空字符尾部填充緩衝區的其餘部分,直到源字符複製+尾部填充空字符總數等於n
,並且最後的陳述是多餘的。如果源字符串長度爲等於或大於目標緩衝區長度,則strncpy()
將停止複製一次N-1
達到字符數,並且最終語句在緩衝區末尾設置空字符。這會導致原始源代碼的「精簡」前綴字符串,但最重要的是,它可以確保您不會超出目標緩衝區的邊界,而後面的字符串API調用將掃描終結符。
上述技術的有用性總是值得商榷的。我是一個C++的人,所以std::string
拯救了我所有這種瘋狂的快樂。但現實情況是這樣的:有時候你會在乎src
是否在其整體到dst
中被複制;有時候你沒有。有用性是很情況依賴。爲了在UI中呈現字符串數據,這不會(可能)重要。對於複製要用於關鍵數據的字符串,部分前綴子字符串不會被接受。當警方向「約瑟夫約翰遜約翰」發出逮捕令時,當他的父親(「約瑟夫約翰遜」)被囚禁入獄時,會有一些解釋要做,因爲權證發行軟件的名字緩衝區只有15個字符。
所有這一切說,你分段故障歸結爲這樣一句話:
strncpy(s1.from_str,src, 100); // length parameter is wrong.
產品召回大膽的聲明,上面:「strncpy()
將永遠寫n
字符由目標緩衝區中引用的地址。」。這意味着上述代碼將總是寫入100個字符到目標緩衝區,在您的情況下只有10個字符寬,因此未定義的行爲,並可能ker-boom。
通過執行糾正這種如果目標緩衝區是一個固定長度的字符數組以下:
strncpy(s1.from_str,src, sizeof(s1.from_str)/sizeof(s1.from_str[0])-1);
s1.from_str[ sizeof(s1.from_str)/sizeof(s1.from_str[0])-1 ] = 0;
參見如何做到這一點對於長度`Ñ字符的動態字符串的先前使用。
你認爲它應該嘗試做什麼,它做什麼是兩個完全不同的東西。 –