2011-05-23 63 views
5
#inlcude <stdio.h> 
#inlcude <stdlib.h> 
#inlcude <string.h> 

int main() { 
    char *buff = (char*)malloc(sizeof(char) * 5); 
    char *str = "abcdefghijklmnopqrstuvwxyz"; 

    memcpy (buff, name, strlen(str)); 

    while(*buff) { 
     printf("%c" , *buff++); 
    } 

    printf("\n"); 

    return 0; 
} 

此代碼打印整個字符串「abc ... xyz」。但「buff」沒有足夠的內存來保存該字符串。 memcpy()如何工作?它使用realloc()嗎?memcpy()使用realloc()嗎?

回答

10

您的代碼有未定義的行爲。若要回答您的問題,,memcpy不使用reallocsizeof(buf)應該足以容納strlen(str)。更少的是崩潰。

輸出可能會打印,因爲它是一個小程序,但在真正的大代碼中會導致難以調試錯誤。更改您的代碼,

const char* const str = "abcdefghijklmnopqrstuvwxyz"; 
char* const buff = (char*)malloc(strlen(str) + 1); 

另外,不要做*buff++,因爲你將失去記憶記錄(你分配什麼)。在malloc()之後,一旦內存使用結束,應該執行free(buff),否則就是內存泄漏。

+3

+1爲直接問題答案。 – 2011-05-23 04:46:11

+0

我想用這個緩衝區在我的真實應用程序中保存一個字符串。該字符串沒有預定義的長度。它會在程序運行時動態增長(附加一些其他字符串...)。我發現的解決方案是分配一些大內存(〜1KB)。我想知道除此之外是否還有其他解決方案?請幫忙。謝謝。 – shan 2011-05-23 05:02:52

+0

@shan,那麼你可以使用'realloc()'(但不是'memcpy()')來達到這個目的。 – iammilind 2011-05-23 05:17:08

8

您可能會打印出整個字符串,但它並不安全,而且您正在寫入和讀取未分配的內存。這會產生未定義的行爲。

memcpy不做任何內存分配。它只是讀取和寫入您提供的位置。它不檢查是否可以這樣做,在這種情況下,如果你的程序沒有崩潰,你是幸運的。

+0

感謝您的回答。但是,如果我不知道字符串的長度如何分配足夠的內存?我想做一個緩衝區。我想避免寫入和讀取未分配的內存。我在代碼中必須做些什麼改變?請幫忙 ?謝謝 – shan 2011-05-23 04:47:56

+0

@shan - 如果你調用'memcpy',並且你知道你要複製多少內存,那麼你就知道你需要分配多少內存。使用'strlen'來查找字符串的長度(它查找終止的空字符)。 – sje397 2011-05-23 04:49:52

+0

是的,除了一個細節外,你使用'strlen',就像你爲'memcpy'所做的一樣。 'strlen'函數不計算終止空字符。因此,在'malloc'和'memcpy'你都需要使用'strlen(str)+ 1'。另外,你不需要乘以malloc中的sizeof(char)'。按照定義'sizeof(char)== 1'。 – andrewdski 2011-05-23 04:53:02

1

memcpy()是如何工作的?

因爲您調用了未定義的行爲。未定義的行爲可能會按照您的預期完成,它可能會做一些完全不同的事情。它甚至可以在同一個程序的不同運行之間有所不同。它也可以格式化您的硬盤,並仍然符合標準(儘管當然這不太可能:P)

未定義的行爲意味着行爲沒有被定義爲做任何事情。任何事情都是有效的,包括你所看到的行爲。請注意,如果您嘗試使用free,那麼您的目標平臺的C運行時可能會抱怨內存。 ;)

1

memcpy不使用malloc。正如你懷疑的那樣,你正在註銷buff的結尾。在你的簡單例子中,這沒有明顯的傷害,但它是不好的。下面是一些可能出問題的「真實」節目的事情:

  • 你可能會繼在內存中分配亂畫的東西你buff導致微妙(或不那麼微妙)的錯誤以後。
  • 您可能在mallocfree內部使用的標頭上塗寫標題,導致下次調用這些函數時出現崩潰或其他問題。
  • 您最終可能會寫入尚未分配給您的進程的地址,在這種情況下,您的程序將立即崩潰。 (我懷疑這是你期待什麼。)

malloc實現,把各地分配的內存映射的防護頁面(通常情況下),程序會在這樣的情況下崩潰。其他實現會檢測到這種情況,但只能在您下次調用mallocfree時(或者當您調用特殊函數來檢查堆時)。