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() 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
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
freeand there’s no need to deallocate the fields separately. The same thing is true for thelabelfield.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_stepandlabel_stepvariables 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 twomallocs.Edit: Your initialization code basically looks like this:
So you don’t actually need
obj_step: you can set directly set the members ofnewstep_button->obj, e.g.: