2011-05-24 86 views
2

麻煩我試圖將雙向鏈接列表映射到GUI。我基本上爲列表中的每個節點創建一個按鈕結構,將節點參數映射到按鈕參數,然後將它們顯示在屏幕上。我可以添加很多按鈕,超過500個,他們似乎保持其獨特的數據,不重疊。但是,當我刪除一個按鈕時,下一個malloc()函數無法創建新按鈕,我只能刪除。如果我擺脫了free()函數,malloc()不再失敗。所以,我的問題是我正確創建和刪除這些結構?結構和malloc()/免費()

該結構取自一個GUI庫,我修改了它以在我的特定硬件上工作。

typedef struct 
{ 
    obj_t obj;  /**< object structure */ 
    string_t label; /**< button label, NULL if no label */ 
    color_t color; /**< color of the button */ 
} button_t; 

typedef struct obj_t 
{ 
    int     x;     /**< x position, relative to parent */ 
    int     y;     /**< y position, relative to parent */ 
    unsigned    width;    /**< component widht */ 
    unsigned    height;   /**< component height */ 
    draw_t    draw;    /**< function to draw the component */ 
    handler_t    handler;   /**< function to handle mouse-input events */ 
    action_t    action;   /**< function to handle user action */ 
    struct obj_t   *parent;   /**< parent of the component */ 
    unsigned    agui_index;  /**< agui structure index */ 
    BOOL     enabled;   /**< if set, component is enabled */ 
    BOOL     visible;   /**< */ 
    BOOL     invalidated;  /**< if set, draw this component */ 
    BOOL     invalidated_child; /**< children need to be redrawn */ 
    BOOL     selected;   /**< component is selected */ 
    BOOL     pressed;   /**< component is pressed */ 
    uintptr_t    tag;    /**< tag for general use */ 
} obj_t; 

typedef struct 
{ 
    int   x;   /**< x position */ 
    int   y;   /**< y position */ 
    char   *text;  /**< string text */ 
    const font_t *font;  /**< string-text font */ 
    color_t  color;  /**< string-text color */ 
    fontstyle_t fontstyle; /**< string-text font style */ 
    align_t  align;  /**< alignment with respect to x and y position */ 
} string_t; 

這些是代碼使用的malloc()的部分:

char *step_name = (char*)malloc(20*sizeof(char)); 
if(step_name == NULL) 
    return -1; 

sprintf(step_name,"STEP %d",curr_job_recipe->curr_step->step_num); 

obj_t *obj_step = (obj_t*) malloc(sizeof(obj_t)); 
if(obj_step == NULL) 
{ 
    free(step_name); 
    return -1; 
} 

string_t *label_step = (string_t*) malloc(sizeof(string_t)); 
if(label_step == NULL) 
{ 
    free(step_name); 
    free(obj_step); 
    return -1; 
} 

button_t *newstep_button =(button_t*) malloc(sizeof(button_t)); 
if(newstep_button == NULL) 
{ 
    free(step_name); 
    free(obj_step); 
    free(label_step); 
    return -1; 
} 

obj_t **objects; // This is a parameter to the function I'm simplifying to save sanity 
objects[curr_index] = &newstep_button->obj; 
obj_step->x = 2; 
obj_step->y = objects[curr_index-1]->y+BUTTON_HEIGHT+1; 
obj_step->width = 316; 
obj_step->height = 60; 
obj_step->draw = button_draw; 
obj_step->handler = button_handler; 
obj_step->parent = AGUI_HANDLE(editrecipeform); 
obj_step->agui_index = 0; 
obj_step->action = editrecipeform_btn5_action; 
obj_step->visible = TRUE; 
obj_step->enabled = TRUE; 
obj_step->selected = FALSE; 
obj_step->pressed = TRUE; 
obj_step->invalidated = TRUE; 
label_step->x = 0; 
label_step->y = 0; 
label_step->text = step_name; 
label_step->font = &helveticaneueltstdltext18_2BPP; 
label_step->color = BLACK; 
label_step->fontstyle = FS_NONE; 
label_step->align = ALIGN_CENTRE; 
newstep_button->obj = *obj_step; 
newstep_button->label = *label_step; 
newstep_button->color = RED; 

然後,當用戶選擇刪除上的按鈕時,執行以下。

button_t *newstep_button = (button_t*) objects[i]; 
obj_t *obj_step = (obj_t*) &newstep_button->obj;     
string_t *label_step = (string_t*) &newstep_button->label; 
free(label_step->text); 
free(label_step); 
free(obj_step); 
free(newstep_button); 

編輯:補充說我在malloc()函數的代碼空間面積

回答

2
obj_t *obj_step = (obj_t*) &newstep_button->obj; 
free(obj_step); 

在這裏,你正試圖釋放一個非指針結構現場留下了一些初始化代碼。你不應該這樣做:當你調用free時,整個結構的內存將被釋放,並且不需要單獨釋放字段。 label字段也是如此。

如果你的結構體具有你用malloc分配的指針字段,你需要在釋放結構本身之前分開釋放它們。

關於您分配的obj_steplabel_step變量,您需要釋放它們,但是您不會在您存儲其值的地方發佈代碼。如果他們沒有在任何地方使用,你可以刪除這兩個malloc s。

編輯:您的初始化代碼基本上是這樣的:

obj_t *obj_step = (obj_t*) malloc(sizeof(obj_t)); 
//... set members of obj_step 
newstep_button->obj = *obj_step; //this will copy the entire struct 

所以,你真的需要不obj_step:您可以設置直接設置的newstep_button->obj的成員,如:

newstep_button->obj.x = 2; 
+0

我不能決定是否投了(因爲你說怎麼樣'obj'件絕對是真的,也許是正確的答案),或者是因爲你所說的關於成員自動釋放的內容(因爲他確實有指針成員,需要單獨釋放)。我會解決投票的問題,但請澄清關於「自動」部分。 – 2011-05-24 15:53:45

+0

@ Ernest:這句話很糟糕,現在好多了? – interjay 2011-05-24 15:56:32

+0

是的,先生,謝謝! – 2011-05-24 15:57:38

0

我沒有看到label_step->text被設置爲任何東西;它可能沒有被設置,或者被設置爲指向未被malloc()分配的塊,並且這是失敗來自的地方。

+0

我編輯它在malloc()代碼區域。 – rawbus 2011-05-24 16:23:25

0

您不存儲由malloc在button_t對象中返回的指針。

變化

typedef struct 
{ 
    obj_t obj;  /**< object structure */ 
    string_t label; /**< button label, NULL if no label */ 
    color_t color; /**< color of the button */ 
} button_t; 

typedef struct 
{ 
    obj_t *obj;  /**< object structure */ 
    string_t *label; /**< button label, NULL if no label */ 
    color_t color; /**< color of the button */ 
} button_t; 

而這些變化在初始化:

newstep_button->obj = obj_step; 
newstep_button->label = label_step; 
newstep_button->color = RED; 

而這些變化在免費:

button_t *newstep_button = (button_t*) objects[i]; 
obj_t *obj_step = newstep_button->obj;     
string_t *label_step = newstep_button->label; 
free(label_step->text); 
free(label_step); 
free(obj_step); 
free(newstep_button); 

如果您釋放的東西不是使用malloc創建的,您所描述的內容聽起來就像典型的行爲。你基本上是在垃圾內存分配列表 - 當malloc試圖找到一些空閒的內存它崩潰。

我將不得不看到更多的代碼,以確保您的所有自由聲明對我來說似乎都是可疑的。爲了弄清楚是否有問題,請出示你在那裏分配空間,每個語句代碼:

free(label_step->text); 
free(label_step); 
free(obj_step); 
free(newstep_button); 
+0

我把它放在malloc()代碼區 – rawbus 2011-05-24 16:22:37

+0

啊,現在我明白你在做什麼了 - 看編輯。 – Hogan 2011-05-24 17:12:35