2011-09-23 43 views
3

我將與Ubuntu 8.04(gcc版本4.2.4)配合使用的程序移植到10.04(gcc版本4.4.3)。我有以下代碼:strstr:使用不同版本的gcc的行爲不同

#include <stdio.h> 
#include <string.h> 

int main(void) { 
    char p[100] = "////abcd"; 
    char *t; 

    /* Remove duplicate slashes, saving only one of them */ 
    while (t = strstr(p, "//")) 
    strcpy(t, t + 1); 

    printf("%s\n", p); 

    return 0; 
} 

結果應該是/abcd,它是用gcc 4.2.4。使用4.4.3,輸出爲/accd

你可以給我一個代碼改變,它會使用兩個版本的gcc給出正確的輸出,並且最好解釋一下這裏發生了什麼。

在此先感謝!

回答

7

你剛剛幸運。

strcpy文檔:

的的strcpy()函數將複製字符串指向S2(包括終止空字節)到陣列指向S1。 如果在重疊的對象之間進行復制,則行爲未定義。

在你的情況下,字符串重疊,你的程序調用未定義的行爲。

一個可能的原因,它曾經工作但不再做的是strcpy可能已被GCC像memmove(即在這種情況下安全)作爲內置實現,但由於性能原因,這改變爲非安全版本。 (這是純粹的猜測。)

要修復它,用memmove而不是strcpy,喜歡的東西:

while (t = strstr(p, "//")) { 
    memmove(t, t+1, strlen(t)); // strlen(t)'s bytes worth of data 
           // will cover the string bytes left 
           // and the \0 terminator 
} 

這不是非常有效,但它會可移植性工作 - memmove必須處理重疊的內存區域。

+3

Johan在**編譯gcc之前**是不吉利的** 4.4.3 – pmg

+0

很酷。代碼庫中塞滿了類似的用法。 :)所以,現在我已經實現了我自己的strcpy來解決這個問題。謝謝! – Johan

+1

@pmg說了什麼。我們都應該爲那些以容易觀察到的方式呈現自己的錯誤而感到幸運,而不是多年來處於休眠狀態。 –

相關問題