проблема со структурами и malloc () / free () - PullRequest
2 голосов
/ 24 мая 2011

Я пытаюсь отобразить двусвязный список в графический интерфейс.Я в основном создаю структуру кнопок для каждого узла в списке, сопоставляю параметры узлов с параметрами кнопок, а затем отображаю их на экране.Я могу добавить много кнопок, более 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 ()

Ответы [ 3 ]

2 голосов
/ 24 мая 2011
obj_t *obj_step = (obj_t*) &newstep_button->obj;
free(obj_step);

Здесь вы пытаетесь освободить неструктурное поле структуры. Вы не должны этого делать: вся память структуры будет освобождена при вызове free, и нет необходимости отдельно освобождать поля. То же самое верно для поля label.

Если в вашей структуре есть поля указателя, которые вы выделили с помощью malloc, вам необходимо освободить их отдельно перед освобождением самой структуры.

Что касается выделенных вами переменных obj_step и label_step, вам нужно их освободить, но из кода, который вы опубликовали, неясно, где вы храните их значения. Если они нигде не используются, вы можете удалить эти два malloc s.

Редактировать: Ваш код инициализации в основном выглядит так:

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;
0 голосов
/ 24 мая 2011

Вы не сохраняете указатели, возвращаемые 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;

и эти изменения в свободном:

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);
0 голосов
/ 24 мая 2011

Я не вижу, чтобы label_step->text был установлен на что-либо;возможно, он не установлен или не указывает на блок, не выделенный malloc(), и именно отсюда происходит сбой.

...