2016-05-18 35 views
-6

我用的示例工作關於SEG故障:不可預測的行爲

char m[10]="dog"; 
strcpy(m+1,m); 

以我CENTOS機的結果如預期:段故障。但在Ubuntu上並沒有發生。然後我添加一個printf(「%s」,m);到Ubuntu上的代碼,令人驚訝的是我得到了「ddog」。 我使用GCC和ubuntu版本是最新的。 誰能告訴我爲什麼結果是不同的。我也檢查了raspbian,我也收到了分段錯誤。

感謝,

+0

「預期」 ←有您的問題。 「未定義的行爲」就是這個意思。 – jthill

+0

謝謝,我的期望是完全錯誤的 – Mahdi

回答

3

這將導致undefined behaviourstrcpy只能用於不重疊的區域之間。

爲了解決這個問題,你可以寫:

memmove(m+1, m, strlen(m) + 1); 
1

m的內存是:

+---+---+---+---+---+---+---+---+---+---+ 
| | | | | | | | | | | 
+---+---+---+---+---+---+---+---+---+---+ 

WHE你初始化:

char m[10] = "dog"; 

前四個要素m被初始化。其餘的都已初始化。

+---+---+---+----+---+---+---+---+---+---+ 
| d | o | g | \0 | ? | ? | ? | ? | ? | ? | 
+---+---+---+----+---+---+---+---+---+---+ 

我正在使用?來指示未初始化的內存位置。他們可以包含任何東西,包括 。通過

strcpy(m+1, m); 

一步一步執行

讓我們走。

步驟1:將m[0]複製到m[1]。所以,你必須:

+---+---+---+----+---+---+---+---+---+---+ 
| d | d | g | \0 | ? | ? | ? | ? | ? | ? | 
+---+---+---+----+---+---+---+---+---+---+ 

步驟2:m[1]被複制到m[2]。所以,你必須:

+---+---+---+----+---+---+---+---+---+---+ 
| d | d | d | \0 | ? | ? | ? | ? | ? | ? | 
+---+---+---+----+---+---+---+---+---+---+ 

第3步:m[2]被複制到m[3]。所以,你必須:

+---+---+---+---+---+---+---+---+---+---+ 
| d | d | d | d | ? | ? | ? | ? | ? | ? | 
+---+---+---+---+---+---+---+---+---+---+ 

strcpy終止,當它遇到源 參數空字符。正如你所看到的,strcpy的終止標準決不會符合 。因此,程序繼續讀取超出有效限制的內存中的數據,並將數據寫入內存超出有效限制。

這是導致未定義的行爲。

要獲得期望的結果,"ddog",你可以使用:

size_t len = strlen(m); 
for (int i = len; i >= 0; --i) 
{ 
    m[i+i] = m[i]; 
}