2013-01-24 77 views
0

一個簡單的程序,下面用malloc和scanf用%s得到一個字符串如下,給我一個我無法理解的輸出。雖然我只「混雜」了5個字節,但我的輸入字符串已超出上述大小,但沒有分段錯誤。 是scanf overiding malloc分配?malloc和scanf字符串

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

int main() { 
    char * name; 
    int SZSTRING; 

    printf("Enter size of name :"); 
    scanf("%d", &SZSTRING); 
    name = (char*) malloc ((SZSTRING + 1) * sizeof(char)); 

    printf("Enter name :"); 
    scanf("%s", name); 
    printf("len of 'name' : %d\n",strlen(name)); 

    printf("name final: \"%s\"\n",name); 
    free(name); 

return 0; 
} 

Output: 

OptiPlex-380:~/gsa/compile$ gcc -o try try.c 
OptiPlex-380:~/gsa/compile$ ./try 
Enter size of name :4 
Enter name :qwertyui 
len of 'name' : 8 
name final: "qwertyui" 

我注意到這裏還有一件事情:與

//scanf("%s", name); 

輸出顯示

len of 'name'= 0 

和 'malloced' 位置實際上memset的爲NULL。但它的calloc而不是malloc,它將分配的字節按照man-page初始化爲0?

+1

這是未定義的行爲,任何事情都可能發生。它甚至可以「工作」。 – hmjd

回答

2

看起來似乎「有效」,但那只是因爲你幸運。當我在一個編譯器上運行你的代碼時,它會在另一個編譯器上「工作」,因爲堆損壞而崩潰。如果你想使用scanf()最好的辦法就是讓scanf()的分配內存爲您提供:

scanf("%ms", &name); // compiled with -std=c99 this will allocate the correct amount 
        // of memory for you. You can use "%as" if you're using -std=c89 

而且記住,scanf()有返回值(它告訴你成功的匹配,輸入項目的數量分配),檢查是否有效是很重要的。

雖然我們在良好做法,你shouldn't typecast the return value of malloc()

另一種方法,不使用scanf(),就是用fgets()代替:

fgets(name, SZSTRING, stdin); 
+1

不應該是'&name'嗎?使用'name'時會出現段錯誤。 – mhutter

+0

@mhutter - 當我輸入答案時的確應該是錯過了它。在3年內第一個獲得這一榮譽的榮譽! ;) – Mike

2

不,它不。但超過分配的緩衝區大小並不總是立即導致分段錯誤。有時候地區會被損壞,效果會在晚些時候甚至從未發生。

+0

所以我明白,我必須手動跟蹤最終字符串的大小。也許循環中的getchar是一個值得信任的選擇? – Aadishri

+0

這是正確的。 – junix

+2

@Aad,你可以使用'fgets()'並指定要讀取的最大字符數。 – hmjd

1

這是可能的,這種情況下會不段錯誤運行。在這種情況下,它只是說你使用了一個你沒有聲稱的空間,損壞了一些可能被其他人「擁有」的內存位置。