结构体和 malloc()/free() 的问题
我正在尝试将双向链表映射到 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
此处您尝试释放非指针结构字段。你不应该这样做:当你调用
free
时,整个结构体的内存将被释放,并且不需要单独释放字段。label
字段也是如此。如果您的结构体具有使用
malloc
分配的指针字段,则需要在释放结构体本身之前单独释放它们。关于您分配的 obj_step 和 label_step 变量,您需要释放它们,但从您发布的代码中不清楚您在哪里存储它们的值。如果它们没有在任何地方使用,您可以删除这两个
malloc
。编辑:您的初始化代码基本上如下所示:
所以您实际上不需要
obj_step
:您可以直接设置newstep_button->obj
的成员,例如: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 thelabel
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
andlabel_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 twomalloc
s.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.:我没有看到
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 bymalloc()
, and that's where the fail is coming from.您没有将 malloc 返回的指针存储在 Button_t 对象中。
更改
为
init: 中的这些更改以及
free: 中的这些更改:
如果您释放不是使用 malloc 创建的内容,那么您所描述的听起来像是典型行为。您基本上是在破坏内存分配列表 - 当 malloc 尝试找到一些可用内存时,它会崩溃。
我必须查看更多您的代码才能确定,但您所有的自由声明对我来说似乎都很可疑。要确定是否存在问题,请显示为每个语句分配空间的代码:
You are not storing the pointers returned by malloc in the button_t object.
Change
to
and these changes in init:
and these changes in free:
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: