2012-03-08 9 views
0

在由教授給出了一些示例代碼: C:strncpy比分配的字符更多然後打印...意外的輸出?

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

int main() 
{ 
    char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    printf("%s\n", alpha); 
    printf("%c\n", alpha[8]); 
    alpha[8] = 'Z'; /* segmentation fault if alpha is declared statically! */ 

    printf("%d\n", sizeof(alpha)); 
    printf("%d\n", strlen(alpha)); 

    char x[10]; 
    strncpy(x, alpha, 26); 
    /* strncpy() will NOT copy or append a '\0' */ 
    printf("%s\n", x); 

    return EXIT_SUCCESS; 
} 

當第一次編譯和運行,程序段錯誤是由於,從我在谷歌搜索,對緩衝區溢出gcc的一個保護機制(幾分鐘看到觸發

printf("%s\n", x);其中x已經被填充了來自alpha的26個字節)。這我相信我明白了。

但是,禁止用gcc -fno堆棧保護器的保護機制的時候,我看到的輸出是:

ABCDEFGHIJKLMNOPQRSTUVWXYZ 
I 
27 
26 
ABCDEFGHZJKLMNOPQRSTUVWXYZKLMNOPQRSTUVWXYZ 

我認爲,因爲strncpy會不空終止字符串,當打印X它實際上可能會打印完整值alpha - 但事實上,它的打印全部爲alpha,然後更多alpha

有人可以提供一些見解嗎?

回答

1

有了這個代碼:

char x[10]; 
    strncpy(x, alpha, 26); 

您正在複製26個字節的數據到一個10字節的數組,這意味着要覆蓋16個字節的任何存儲器正好是鄰近「×」。在這種情況下,它看起來像是什麼與「x」相鄰的是「alpha」,所以你破壞了初始數組的一部分

當你「printf」x時,它會一直打印,直到它遇到一個空字節,取出你複製的所有26個字節,再加上內存中的其他內容(「alpha」的倖存內容),直到下一個空字節爲止。

2

你只是幸運。超出數組範圍的結果導致未定義的行爲

未定義的行爲意味着任何行爲都是可能的,它總是不會導致分段錯誤,它只是意味着程序無效並可能顯示任何行爲。

是的,你的程序有時甚至可以根據需要工作,但它仍然是按照標準成形的程序。

2
char x[10]; strncpy(x, alpha, 26);  
/* strncpy() will NOT copy or append a '\0' */ 
printf("%s\n", x); 

要strncpy()函數,你逝去,26 n的值,所以它複製26個字符,但是在打印時用printf,printf的將嘗試尋找一個「\ 0」作爲終止字符字符串。在這種情況下,'0'恰好在「KLMNOPQRSTUVWXYZ」之後出現。

所以,在現實中,當你做一個數組越界,你可以得到任何形式的結果,崩潰,一個字符串,它是太長等

+0

我希望有一個確定性的原因,'KLMNOPQRSTUVWXYZ'會在'ABCDEFGHZJKLMNOPQRSTUVWXYZ'之後直接打印出來;我想如果在Z之後出現空字符,K-Z秒輸出將不會顯示。 – Joseph 2012-03-08 06:00:30

+1

您僅複製26個字符,因此可能在alpha中的'Z'後面出現的空字符不會被複制。但是,一個數組越界也不能保證,因爲對於x只分配了10個字節,x的第10個字節後的內存不屬於你,並且可以在任何方向操作 – Jay 2012-03-08 06:04:58

+0

好點,謝謝! – Joseph 2012-03-08 06:10:01

1

的問題是關於內存佈局。
在這個程序中,「alpha」就在「x」之後。所以當你打電話

strncpy(x, alpha, 26); 

alpha的數據正在被修改。

相關問題