2011-12-22 60 views
21

我想知道爲什麼下面的代碼isnt't工作分配內存和保存串在C

int main(int argc, char **argv) 
{ 
    char *test = (char*) malloc(12*sizeof(char)); 
    test = "testingonly"; 
    free(test); 
} 

考慮這件事後,我的假設是,我第一次在內存12個字符,但在分配分配空間下一行在棧上創建一個char數組,並將其內存地址傳遞給測試。所以free()試圖釋放堆棧中不允許的空間。那是對的嗎?

那麼在堆上保存字符串的正確方法是什麼?以下是常用的方法嗎?

int main(int argc, char **argv) 
{ 
    char *test = (char*) malloc(12*sizeof(char)); 
    strcpy(test, "testingonly"); 
    free(test); 
} 
+4

第一溶液示出了經典的內存泄漏;你得到一個指向一些分配的內存的指針,然後當把指針指向字符串文字指向'test'時,它就失去了唯一的引用。此後,沒有合法的方式來引用分配的內存 - 泄漏。 – 2011-12-22 06:44:32

+2

永遠不要在C中綁定malloc的結果,這是毫無意義的,只能隱藏錯誤和編譯器警告。 – Lundin 2011-12-22 07:37:29

+2

是 - 使用'strcpy'或'strncpy'或'memcpy'。 strncpy比strcpy更好,因爲它有助於避免在最多N個字符處複製時出現緩衝區溢出問題。 – 2011-12-22 08:55:29

回答

8

您已回答您的問題。從本質上講,strcpy是複製字符串的適當方式。

+0

只要你知道在目標字符串中已經分配了合適的內存,並且兩個字符串都是空的。 – Dave 2011-12-22 07:55:49

5

第一個版本不會在堆棧中創建一個字符串,但您確認在賦值後不允許您使用free。字符串文字通常存儲在內存的常量/只讀部分。該作業不會複製任何內容,只會讓test指向該內存區域。你不能釋放它。您也無法修改該字符串。

你的第二段代碼是正確的和通常的。如果您的實施具有該功能,您可能還需要查看strdup

+0

+1爲常量/只讀部分 – 2011-12-22 07:56:56

+0

'strncpy'不*是'strcpy'的更安全版本。它可以使目標陣列不終止。這很少是正確的解決方案。 – 2011-12-22 08:01:18

+0

@Keith:對,刪除了那個引用。 'strdup'雖然很不錯(假設你知道你的輸入是1.一個有效的C字符串和2.可接受的大小 - 無論你的應用程序是什麼)。 – Mat 2011-12-22 08:31:39

4

那麼你是正確的。現在讓我們來檢查第一段代碼。

char *test = (char*) malloc(12*sizeof(char)); 

上面的代碼沒有問題。

test = "testingonly"; 

在這裏,您修改了導致內存泄漏的指針test。而當你試圖釋放你不是釋放實際分配的指針,而是一個「唯一」的文字指向。文字指向在通常情況下無法覆蓋的常量內存。

現在關於第二段代碼,這將工作得很好,因爲您明確地將數據從文字所在的地方複製到您的test指向的堆。

你的第二點是strcpy是一種常用的方法。其他方法是'memcpy',如果你正在複製原始字節。

注意:文字不存儲在堆棧中。但是你不能修改存儲文字的位置。

+0

+1「這樣可以正常工作,因爲您明確地將數據從文字所在的位置複製到了測試指向的堆中」 – 2011-12-29 13:13:26

57
char *test = (char*) malloc(12*sizeof(char)); 

     +-+-+-+-+-+-+-+-+-+-+-+-+ 
test--->|x|x|x|x|x|x|x|x|x|x|x|x| (uninitialized memory, heap) 
     +-+-+-+-+-+-+-+-+-+-+-+-+ 

test = "testingonly"; 

     +-+-+-+-+-+-+-+-+-+-+-+-+ 
test + |x|x|x|x|x|x|x|x|x|x|x|x| 
    | +-+-+-+-+-+-+-+-+-+-+-+-+ 
    | +-+-+-+-+-+-+-+-+-+-+-+-+ 
    +->|t|e|s|t|i|n|g|o|n|l|y|0| 
     +-+-+-+-+-+-+-+-+-+-+-+-+ 

free(test); // error, because test is no longer pointing to allocated space. 

而是改變指針test的,你需要將字符串"testingonly"複製到使用例如分配的地方strcpy或使用strdup。請注意,如果內存不足,功能如mallocstrdup會返回NULL,因此應進行檢查。

char *test = (char*) malloc(12*sizeof(char)); 
strcpy(test, "testingonly"); 

     +-+-+-+-+-+-+-+-+-+-+-+-+ 
test--->|t|e|s|t|i|n|g|o|n|l|y|0| 
     +-+-+-+-+-+-+-+-+-+-+-+-+ 

char *test = strdup("testingonly"); 

     +-+-+-+-+-+-+-+-+-+-+-+-+ 
test--->|t|e|s|t|i|n|g|o|n|l|y|0| 
     +-+-+-+-+-+-+-+-+-+-+-+-+ 
+4

+1讚賞您的解釋。 – dicaprio 2011-12-22 09:04:07

+0

謝謝!!!!大 – 2015-10-27 23:20:01

0

代碼

#include <stdio.h> 
int main(int argc, char **argv) 
{ 
    char *test = (char*) malloc(12*sizeof(char)); 
    strcpy(test, "testingonly"); 
    printf("string is: %s\n",test); 
    free(test); 
    return 0; 
} 

將工作

0

這是分配內存:

char *string; 
string = (char *) malloc(15); 

這是用於保存數據:

strcpy(str, "kavitajain"); 
printf("String = %s, Address = %u\n", str, str);