2014-02-23 53 views
0

我的問題是爲什麼下面的代碼片段不會崩潰?當緩衝區很小以容納一些數據時會發生什麼

int main(int argc, const char * argv[]) 
{ 
    const char* source = "SomeText"; 
    char* dest = (char*)malloc(sizeof(char)); // isn't this wrong ? 

    strcpy(dest, source); 

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

    free(dest); 


    return 0; 
} 
+0

這確實是錯誤的,並調用未定義的行爲。 – jpw

回答

2

strcpy當緩衝區太小而不能容納被複制的字符串時會溢出緩衝區。這會導致未定義的行爲,甚至導致程序崩潰(segfault),因爲strcpy將嘗試寫入未分配給緩衝區的內存。你不能依靠發生的事情。下次你運行你的程序時,它可能會崩潰。這裏有一些我建議的修復。

// in main 

const char *source = "SomeText"; 
char *dest = malloc(strlen(source) + 1); // +1 for the null byte at the end 
if(dest != NULL) { // check for NULL 
    strcpy(dest, source); 
    printf("%s\n", dest); 
    free(dest); 
} 
else { 
    printf("not enough memory\n"); 
} 

strlen不計算在字符串中的空字節,所以你必須分配一個額外的字節爲它被strcpysource字符串複製。您應該檢查malloc的結果爲空。此外,你不應該投下malloc的結果。如果忘記包含stdlib.h頭文件,則沒有任何好處,並且會導致錯誤。

+0

你關於malloc轉換結果的觀點並不完全正確。大多數編譯器(如MSVC++)將會(也應該)在這種情況下產生一個錯誤。爲特定類型的指針分配void *總是必須通過reinterpret_cast <>或c-style類型的顯式強制轉換完成。 –

+0

@MateuszGrzejek我在'C'的語境中說話。你是對的。在'C++'中,你確實需要施加'malloc'的結果,否則編譯器會拋出一個錯誤。 – ajay

+0

現在我看到那個小的,幾乎看不見的標籤,對不起:) –

1

因爲它是未定義行爲和可能發生在工作或沒有。寫入未分配的空間是一種冒險的操作,不保證成功。

1

在這種情況下的行爲是未定義的。事實上,保留位置以外的內存被覆蓋。這個記憶可以保存一些重要的信息。它可能被映射到進程的地址空間或沒有。如果未映射,則會發生系統錯誤。如果它被映射,那麼這個內存最有可能包含malloc和free的正確工作所需的值,所以你可能會期望在下一個malloc或free時發生崩潰。如果覆蓋大部分內存,則可以寫入其他動態分配的緩衝區。

在你的情況下,你只覆蓋保留地方以外的8個字節。最有可能的是那8個字節被映射到地址空間並且根本不被使用。這就是爲什麼沒有發生。確切的行爲取決於malloc和免費的特定實現。

1

好運?

但通常malloc抓取方便操作系統的內存。所以也許它是1K

相關問題