I'm trying to map a doubly linked list to a GUI. I basically create a button structure for every node in the list, map the nodes parameters to the buttons parameters, and then display them on the screen. I can add a lot of buttons, more than 500, and they seem to maintain their unique data and not overlap. However, when I delete just one button, the next malloc() function fails for creating a new button and I can only delete. If I get rid of the free() functions the malloc开发者_JAVA技巧() no longer fails. So, my question is am I creating and deleting these structs correctly?
The structs are taken from a GUI library that I modified to work on my specific hardware.
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;
These are the pieces of code using the 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;
Then when the user selects delete on a button the following is executed.
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);
EDIT: added some initialization code that I left out in the malloc() code space area
obj_t *obj_step = (obj_t*) &newstep_button->obj;
free(obj_step);
Here you are attempting to free a non-pointer struct field. You shouldn't do this: The entire struct's memory will be deallocated when you call free
and there's no need to deallocate the fields separately. The same thing is true for the label
field.
If your struct had pointer fields that you allocated with malloc
, you'd need to free them separately before freeing the struct itself.
Regarding the obj_step
and label_step
variables that you allocated, you need to free them, but it isn't clear from the code you posted where you're storing their values. If they aren't used anywhere, you can remove these two malloc
s.
Edit: Your initialization code basically looks like this:
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
So you don't actually need obj_step
: you can set directly set the members of newstep_button->obj
, e.g.:
newstep_button->obj.x = 2;
I don't see label_step->text
being set to anything; it's possible that it's not being set, or being set to point to a block not allocated by malloc()
, and that's where the fail is coming from.
You are not storing the pointers returned by malloc in the button_t object.
Change
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;
to
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;
and these changes in init:
newstep_button->obj = obj_step;
newstep_button->label = label_step;
newstep_button->color = RED;
and these changes in free:
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);
What you describe sounds like typical behavior if you free something that was not not created using malloc. You are basically trashing the memory allocation lists - when malloc tries to find some free memory it crashes.
I would have to see more of your code to be sure but all of your free statements seem suspect to me. To figure out if there is a problem please show the code where you allocate the space for each of these statements:
free(label_step->text);
free(label_step);
free(obj_step);
free(newstep_button);
精彩评论