3

In preparation for my final project, I am writing a C program that handles task lists. It utilizes a nested struct. For every line it reads from a file it creates a struct of type task. Each task then is being put into a struct of type tasklist_container.

My problem is that I cannot free the memory that I malloc'd like this

task* new_task = malloc(sizeof(task));

and

tasklist_container* main_tasklist = malloc(sizeof(tasklist_container));

Any ideas?

Typedefs for the mentioned structs:

// definition of task  
typedef struct task  
{
    int  id;  
    bool completed;  
    int  priority;  
    char description[TASKLENGTH+1];  
    int  context[TASKLISTLENGTH/WORDLENGTH];  
    int  number_of_contexts;  
    int  project[TASKLISTLENGTH/WORDLENGTH];  
    int  number_of_projects;  
}
task;

// definition of tasklist container  
typedef struct tasklist_container  
{
    task* list[TASKLISTLENGTH];  
    int   number_of_tasks;  
}
tasklist_container;

Update 0: I've got a follow-up question. My program creates a task like

task* new_task = malloc(sizeof(task)); 

and then nests the new task into a tasklist_container with

tasklist_container tasklist = malloc(sizeof(tasklist_container));
tasklist -> list[tasklist -> number_of_tasks] = new_task; 

My Question: How do I free the firstly malloc()'d memory that new_task points to?

My understanding is that new_task and tasklist->list[] point to the same block of memory. Freeing new_task would also free tasklist->list[]. Is that correct?

5

When you allocate memory by calling malloc(), and you want to free that memory, you have to call free() on every pointer that you initialized it with a call to malloc().

For example, if you have something like

tasklist_container *cont = malloc(sizeof(tasklist_container)); // 1 allocation

for (int i = 0 i < TASKLISTLENGTH; i++)
{
    cont -> list[i] = malloc(sizeof(task)); // TASKLISTLENGTH allocations in total
}

and you want to free the allocated memory, you have to call free() on every pointer to a task in list that you initialized it with a call to malloc() before freeing cont itself. For example,

for (int i = 0 i < TASKLISTLENGTH; i++)
{
    free(cont -> list[i]);
}

free(cont);

In case you have a singly-linked-list for example, you may do that recursively since each element is accessed via the element before it!


Update 0:

Well, there's no such thing

tasklist -> list[]

but I guess you meant

tasklist -> list[tasklist -> number_of_tasks] 

And yes, if you set tasklist -> list[tasklist -> number_of_tasks] to new_task, both will point to the same block of memory. You can call free() on either of them to free that block of memory.

Also, keep in mind that if number_of_tasks is equal to TASKLISTLENGTH, that might get you into troubles because that would be an invalid read/write since list[TASKLISTLENGTH] is beyond the array boundaries.

| improve this answer | |
  • Thank you. A good explanation. I've got a follow-up question. My program creates a task (struct) task* new_task = malloc(sizeof(task)); and then nests the new task into the tasklist struct with tasklist->list[tasklist->number_of_tasks] = new_task; My Question: How do a free() the fist malloc for the new task. My understanding is that "new_task" and "tasklist->list[]" point to the same block of memory. Freeing "new_task" would also free "tasklist->list[]". Is that correct? – Christian Weh Jul 15 '14 at 11:43
  • @ChristianWeh I just updated my answer! :) – Kareem Jul 15 '14 at 12:12
  • True: I meant tasklist -> list[tasklist -> number_of_tasks] – Christian Weh Jul 15 '14 at 12:36
  • @ChristianWeh feel free to vote the answer up and accept it if it was helpful! – Kareem Jul 15 '14 at 12:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .