2011-09-21 56 views
1

也許是一個不好的話題,但考慮到下面的代碼,我是否也需要free(player->name)釋放記憶,所有?

#include <stdio.h> 

struct Player 
{ 
     char *name; 
     int level;  
}; 

int main() 
{ 
    struct Player *player; 
    player->name = malloc(sizeof(player->name)*256); 
    player->name = "John"; 

    printf(player->name); 

    free(player); 

    printf("\n\n\n"); 
    system("PAUSE"); 
    return 0; 
} 
+7

你需要一本好書。急。 – sbi

回答

15

哦,男孩,從哪裏開始?你真的需要一本好書。嘆。讓我們開始在main()頂部:


struct Player *player; 

定義一個指針struct Player,但它不會初始化。因此,它具有或多或少的隨機價值,指向某個記憶。此

player->name = malloc(sizeof(player->name)*256); 

現在寫入該隨機位置的份malloc()獲得一塊內存的地址。通過未初始化的指針寫入內存調用未定義的行爲。之後,所有投注都關閉。無需再看看你的程序。不幸的是,你偶然會寫入到你的進程所擁有的一塊內存中,所以它不會立即崩潰,讓你意識到這個問題。

有兩種方法可以改善這種情況。要麼堅持指針,並指向分配給Player對象的一塊內存。你可以致電malloc(sizeof(Player)來獲得它。
或者只是使用本地,自動(又名基於堆棧的)對象:

struct Player player; 

編譯器將生成的代碼的堆棧它上分配內存,並會自動釋放它。這是最簡單的,當然應該是你的默認值。


但是,您的代碼有比這更多的問題。

player->name = malloc(sizeof(player->name)*256); 

在堆上分配連續的存儲到256個指針存儲字符,並分配所述第一指針的player->name地址(一個char*的地址,因此char**)(一char*)。坦率地說,我感到驚訝,即使編譯,但我更習慣於C++更嚴格的類型執行。無論如何,你可能就要代替的是爲256個字符分配內存:

player->name = malloc(sizeof(char)*256); 

(由於sizeof(char),顧名思義,1,你經常會看到這樣的malloc(256)。)
然而,有更多的這種:爲什麼是256?如果我傳遞一個1000字符長的字符串會怎樣?不,只是爲更長的字符串分配空間不是解決這個問題的方法,因爲我可以將它傳遞給更長的字符串。因此,要麼1)固定的最大字符串長度(只是聲明Player::name是一個char陣列的長度,而不是char*)並在代碼執行此限制,或2)找出動態所需要的長度,在運行時間,並準確地分配所需的內存(字符串長度加1,終止'\0' char)。

但它變得更糟。這

player->name = "John"; 

然後分配給player->name文字字符串的地址,通過覆蓋在malloc()你保存它的唯一變量分配的內存的地址,讓你失去的,泄漏的內存。
但是C字符串並不是一流的公民,所以你不能指定它們。它們是字符數組,按慣例以'\0'結尾。要複製它們,您必須逐個字符地複製它們,無論是循環還是最好通過調用strcpy()

要雪上加霜的是,你以後嘗試釋放內存字符串文字生活

free(player); 

從而極有可能嚴重擾亂堆管理器的數據結構。再說一遍,你似乎不太幸運,因爲這不會導致立即崩潰,但代碼似乎按照預期工作是未定義行爲最糟糕的可能性之一。如果不是所有的賭注都被剝離,他們現在徹底的會是。


對不起,如果這聽起來譴責,它確實不是這個意思,但你肯定和嚴重搞砸了這一個。爲了總結這件事:

  1. 你需要一個良好的C++的書。馬上。 Here是C程序員在Stack Overflow上彙編的好書的列表。 (我是一名C++程序員,所以我不會評論他們的判斷,但是K & R肯定是個不錯的選擇。)

  2. 你應該立即初始化所有的指針,或者用現有的地址有效的對象,或分配的內存地址,以保存正確類型的對象,或使用NULL(稍後可以輕鬆檢查)。特別是,你不能嘗試讀取或寫入一段未分配給你的內存(在堆中動態分配或自動分配給你)。

  3. 你需要free()這是通過調用malloc()恰好一次獲得的所有內存。

  4. 您不能嘗試free()任何其他內存。


我敢肯定還有更多的代碼,但我會在這裏停止。 我有沒有提到你需要一本好的C書?因爲你這樣做。

+1

+1 WOW!誰需要[sbi](http://stackoverflow.com/users/140719/sbi)的書? :D – pmg

0

player不需要被釋放,因爲它從來不是malloc'd,它只是一個本地堆棧變量。由於它是動態分配的,因此需要釋放player->name

int main() 
{ 
    // Declares local variable which is a pointer to a Player struct 
    // but doesn't actually point to a Player because it wasn't initialised 
    struct Player *player; 

    // Allocates space for name (in an odd way...) 
    player->name = malloc(sizeof(player->name)*256); 

    // At this point, player->name is a pointer to a dynamically allocated array of size 256*4 

    // Replaces the name field of player with a string literal 
    player->name = "John"; 


    // At this point, the pointer returned by malloc is essentially lost... 
    printf(player->name); 

    // ?!?! 
    free(player); 

    printf("\n\n\n"); 
    system("PAUSE"); 
    return 0; 
} 

我猜你想要做這樣的事情:

int main() { 
    struct Player player; 
    player.name = malloc(256); 
    // Populate the allocated memory somehow... 

    printf("%s", player.name); 
    free(player.name); 
} 
+0

'player'可能* *需要被釋放。當然,它也需要首先配合,它不在提供的代碼中。 – interjay

0

你必須free()一切,你malloc()你必須malloc()未在編譯時分配的一切。

所以:

必須的malloc player,你必須釋放player->name

0

好了,你的變量的球員是一個指針,你還沒有初始化,因此,指向一個隨機的內存位置。

您首先需要爲player分配內存player->name,然後爲player-> name分配內存。

malloc()分配的任何內存需要釋放與free()

看看thisthis

0

這是可怕的代碼。爲什麼?首先你爲player-> name分配內存。 malloc返回指向已分配內存的指針。在下一步你會失去這個指針值,因爲重新指派player-> name指向靜態的「John」字符串。也許你想使用strdup或sprintf函數?

此外,最大的錯誤是使用未初始化的指針播放器結構。試着想象它可以指向隨機存儲器位置。所以最好在malloc的幫助下爲你的結構分配內存。或者不要使用指針來構造和使用真正的結構變量。