2014-02-06 50 views
1

在一個循環中,我malloc一定量的內存,用它來存儲一些字符串。我需要採取哪些步驟,然後才能在循環中使用SAME變量名稱中的malloc一些其他內存量?

當循環發生時,我將不得不malloc另一個內存量,我已經使用了相同的 變量。內存量取決於用戶的輸入。代碼是這樣 以下,(我已經簡化它)

int thisMany; 
char *message = NULL; 
while (1) 
{ 
    printf("How many characters will you type?"); 
    scanf("%d\n", thisMany); 

    message = malloc(sizeof(char*)*(thisMany+1)); 
    message[thisMany+1] = '\0'; 

    for (;thisMany > 0; thismany--) 
    { 
     message[thisMany] = a; 
    } 
    printf("%s", message); 

    /* this is the stage where I don't know what to do with 'message' 
    in order for the code to work after the loop */ 
} 

我一直在使用「自由(消息)」和一些其他的東西嘗試。請讓我知道,如果你知道會使這項工作的東西。

+1

'消息[thisMany + 1] =「\ 0」;'是因爲它寫入過去分配的數組的末尾未定義的行爲。除此之外,爲了避免內存泄漏,您必須在重新分配指針之前釋放(消息); – 2014-02-06 20:37:17

+2

另外,它應該是'sizeof(char)'而不是'sizeof(char *)'(考慮它),但是對於**正是這個原因,**你不應該對這個類型進行硬編碼。 'sizeof message [0]'是寫這個最安全的方法。 – 2014-02-06 20:39:24

+0

您還應該通過檢查'malloc'的返回值來檢查內存分配是否成功。 –

回答

2
while (1) 
{ 
    printf("How many characters will you type?"); 
    scanf("%d\n", thisMany); 

你在這裏的分配是不正確的:你想分配一個字符指針,給定數量的字符。因此,它應該是:

message = (char *)malloc(sizeof(char)*(thisMany+1)); 

    // Always verify *allocs. They're mischievous at best, and often evil. 
    if (NULL == message) { 
     fprintf(stderr, "Out of memory!\n"); 
     exit(-1); 
    } 

有沒有做,但是,因爲的sizeof(字符*)是四個或八個次比的sizeof(char)的大,所以你超過必要分配更多的內存的傷害。但是,現在這行代碼變得危險:

message[thisMany+1] = '\0'; 

您已經分配thisMany + 1個字符,編號從0到thisMany。所以這個Many + 1個字符超出了分配的內存;所謂的「關閉」緩衝區溢出。它應該是:

// One less than the number given to malloc() 
    message[thisMany] = '\0'; 

最後:

/* this is the stage where I don't know what to do with 'message' 
    in order for the code to work after the loop */ 

你需要做的是免費你分配的內存。

free(message); message = NULL; 

將消息重新分配給NULL不是絕對必要的,但我覺得它非常有用;在被釋放後,message仍指向分配的內存區域,該內存仍具有相同的內容。所以,你可以做

free(message); 
    printf("%s\n", message); 

有時,也許經常,這將實際工作,隱藏着一個潛在的災難性錯誤。

將消息設置爲NULL可以保證不會發生這種情況,並且可以提高任何不正確的使用情況都足以引起注意的可能性。它在這方面使行爲具有確定性,這對於捕捉錯誤來說更好。

正如已經指出的,替代方法是在循環前將消息設置爲NULL,然後使用realloc而不是malloc。當傳遞NULL參數realloc()將表現就像malloc

message = NULL; 
for (;;) { 
    // Loop 
    message = realloc(...); 
    if (NULL == message) { 
     ... 
    } 
} 
// finally free message outside the loop. 
// Checking that it is *not* NULL, in case the check above did not exit 
// but just, say, printed an error message and exited the loop via break 
if (message != NULL) { 
    free(message); message = NULL; 
} 
+2

「將消息設置爲NULL可以確保任何不正確的用法都會立即被捕獲。取消引用'NULL'與取消引用任何其他無效指針的行爲是相同的未定義行爲。 (在實踐中,調試NULL解引用比較容易,但根本沒有任何擔保。) – 2014-02-06 20:52:10

+0

是的,有些情況下將message設置爲NULL不足以造成明顯的破壞 - printf()是一個例如:它只會打印「(null)」。事實上,我通常在更危險的情況下使用指針:-)但是,謝謝,我會糾正的。 – LSerni

+0

@iserni謝謝。 (順便說一句,'printf()'行爲就是庫編寫者聰明,謹慎和善良;這個函數不需要檢查NULL。很多程序員依賴大多數現代C庫來做這件事。 ..) – 2014-02-06 20:57:33

0

當您完成messageprintf之後)後,您應該將free (message)釋放。

或者你可以realloc它而不是malloc-它。

相關問題