char r[40];
strcpy(r,"abcdef");
strcat(r,r);
我的程序在第三行崩潰?如果使用相同的陣列作爲兩個參數,strcat()崩潰
更換strcat的(R,R);通過strcat(r,「abcdef」);工作正常,但....爲什麼呢?
char r[40];
strcpy(r,"abcdef");
strcat(r,r);
我的程序在第三行崩潰?如果使用相同的陣列作爲兩個參數,strcat()崩潰
更換strcat的(R,R);通過strcat(r,「abcdef」);工作正常,但....爲什麼呢?
strcat()
從輸入讀取並將其複製到輸出,直到它在輸入中找到一個\0
終止符。通過爲輸入和輸出指定相同的數組,您正在修改正在讀取的輸入。
你必須檢查你的編譯器的具體實現的strcat()
,但如果你跟蹤通過一個簡單的執行類似以下,你應該爲什麼你的代碼崩潰後的一段時間看:
char *strcat(char *dest, const char *src)
{
char *ret = dest;
if (dest && src)
{
while (*dest != 0)
++dest;
while (*str != 0)
*dest++ = *src++;
*dest = 0;
}
return ret;
}
的while (*dest != 0)
循環後, dest
現在指向輸入的終止符\0
。在while (*str != 0)
循環的第一次迭代,然後替換終止與a
,從而導致循環到它應該不再停止。最終,循環將超過輸入的範圍,並開始閱讀周圍的內存,並最終如果沒有找到擊球無效的內存之前另一\0
字節就會死機。
根據strcat(3)
:
的
strcat()
功能追加SRC字符串到DEST串,覆蓋在dest的端終止空字節(「\ 0」),然後將一個空結尾字節。 該字符串可能不重疊,且dest字符串必須有結果了足夠的空間。
原因是strcat在本例中的第一件事是覆蓋char * r的終止空值。然後它會遍歷r,尋找它被覆蓋的空值,最終轉移到不安全的內存中(具體取決於堆棧的方向)
解決方案類似於strncat(r,r,strlen(r))它將在空值被覆蓋之前捕獲R的長度。
遲到的回答。只是想添加一些「圖形」的解釋。
如果您考慮如何實現strcat
,它會在源字符串的第一個字符處初始化一個指針,並逐個遍歷源字符,直到達到其空字節。但是由於源字符串和目標字符串相同,因此可能會發生以下情況。
存儲器開始了這樣的:
a b c d e f \0
源極(S)和dest(d)指針都指向a
上函數入口。該DEST指針移動到結束,我們準備複製
s d
a b c d e f \0
s d
a b c d e f a
s d
a b c d e f a b
s d
a b c d e f a b c
s d
a b c d e f a b c d
s d
a b c d e f a b c d e
s d
a b c d e f a b c d e f
s d
a b c d e f a b c d e f a
你可以看到,源指針不會達到其終止null字節,因爲這讓一開始疲憊不堪。最終我們會在這裏耗盡空間。
因此,由於這是一種可能的情況,所以strcat
的定義不允許兩個字符串重疊。這種方式可以自由使用基本的實現。
想想如何自己實現'strcat()'這可能是一個很好的學習經驗(這是一個非常簡單的函數)。然後檢查您的實現是否處理自串聯,以及您可能需要做些什麼才能使其能夠處理它。然後考慮是否每個調用'strcpy()'的人都應該支付一些功能,比如自連接(self-concatenation),這些功能可能很少使用。 –