开发者

trouble with structs and malloc()/free()

开发者 https://www.devze.com 2023-03-07 22:08 出处:网络
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 scr

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 mallocs.

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);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号