结构体和 malloc()/free() 的问题

发布于 2024-11-09 11:10:38 字数 4231 浏览 0 评论 0原文

我正在尝试将双向链表映射到 GUI。我基本上为列表中的每个节点创建一个按钮结构,将节点参数映射到按钮参数,然后将它们显示在屏幕上。我可以添加很多按钮,超过 500 个,并且它们似乎保持其独特的数据并且不重叠。但是,当我只删除一个按钮时,下一个 malloc() 函数无法创建新按钮,我只能删除。如果我摆脱 free() 函数,则 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() 代码空间区域中遗漏的初始化代码

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

柳絮泡泡 2024-11-16 11:10:38
obj_t *obj_step = (obj_t*) &newstep_button->obj;
free(obj_step);

此处您尝试释放非指针结构字段。你不应该这样做:当你调用free时,整个结构体的内存将被释放,并且不需要单独释放字段。 label 字段也是如此。

如果您的结构体具有使用 malloc 分配的指针字段,则需要在释放结构体本身之前单独释放它们。

关于您分配的 obj_step 和 label_step 变量,您需要释放它们,但从您发布的代码中不清楚您在哪里存储它们的值。如果它们没有在任何地方使用,您可以删除这两个 malloc

编辑:您的初始化代码基本上如下所示:

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;
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;
情绪少女 2024-11-16 11:10:38

我没有看到 label_step->text 设置为任何内容;它可能没有被设置,或者被设置为指向未由 malloc() 分配的块,这就是失败的来源。

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.

梦魇绽荼蘼 2024-11-16 11:10:38

您没有将 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;

init: 中的这些更改以及

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

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

如果您释放不是使用 malloc 创建的内容,那么您所描述的听起来像是典型行为。您基本上是在破坏内存分配列表 - 当 malloc 尝试找到一些可用内存时,它会崩溃。

我必须查看更多您的代码才能确定,但​​您所有的自由声明对我来说似乎都很可疑。要确定是否存在问题,请显示为每个语句分配空间的代码:

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

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文