Does the struct get freed this way in C? - c

I have the following struct which I use to implement a priority queue
struct q_element
{
//Declaration of struct members
int element;
int priority;
struct q_element *next_element;
};
and I use a pointer to a struct 'cur' to start from the first item in the queue
struct q_element* cur = start_element;
and keep moving until I find the one I want to delete from list.
while (cur->priority!=max_priority)
cur = cur->next_element;
Does the following line of code actually free the struct? Because 'cur' is a pointer to the struct I wasn't completely sure.
free(cur);

You need to pass a pointer to free, so free(cur) is the way to go, assuming that the struct itself has been allocated using malloc/calloc/realloc. Specifically, if you allocated your curr in the automatic memory (i.e. on the stack) you are not supposed to call free on it.
It looks like q_element is part of a linked list. Freeing the struct itself will not free other structs pointed to by it, so if you'd like to free the struct along with its tail, you need to write a loop.
Finally, when you free memory pointed to by some pointer in your program, it is a very good idea to assign NULL to the pointer that you freed to avoid accidental double-freeing and undefined behavior on accessing freed memory.

Related

Freeing a pointer to structure containing an array

I have some issues, maybe coming from a misunderstanding of how the function "free" works.
Basically I have defined a structure like this
typedef char parola[11]
typedef struct _node node
struct _node
{
parola wrd;
node *padre;
node *Ts;
node *Td;
};
Later in the code I allocate memory for a node using malloc:
node *r
r = (node *) malloc(sizeof(node));
And i create binary search trees allocating memory for every single node in this way.
When I try to remove a node in a bst, I pass a pointer to that node *n. I think I nail the recursive procedure, but then when it comes to using free() on the pointer to the node, that doesn't seem to work. I am sure of it because if I try to print "parola" in the node, it does actually print the word that was contained there after deallocating the memory.
node *n
.../*in another function*/
free (n)
printf("%s\n",n->wrd)
/*This does print the word inside the node after the deallocation*/
What am I missing here? Do i need to use free() in a different way?
Thanks for your help.
In C, free doesn't wipe the data. It just says "I'm not using it any more; you can use it for something else." If nothing needs to use it in that time, it won't be overwritten.
However, you can't guarantee that it won't be overwritten. Using stuff after it's freed is an excellent way to have your program suddenly, unpredictably fail at the worst possible moment.
(Make sure you free the node(s) you're pointing to before you throw away (or free) their last pointer(s), and make sure you only free each thing once!)

Is freeing a dynamically allocated array same as freeing a linked list?

Suppose I have a struct that looks like this:
typedef struct node{
char **word_ptrs;
int value;
struct node *next;
} Node;
and I have dynamically allocated spaces for the linked list, as well as the word_ptrs within this struct.
For example:
Node *head = malloc(sizeof(Node)); // not important, what I care is not this node.
head->word_ptrs = malloc(10 * sizeof(Node)); // I care about this.
My question is: I know how to free the linked list, but I feel confused when I try to free the dynamically allocated array. When I try to free the array above, should I just directly free the entire array? Or I should go to free every single char * within that array?
Thanks.
You should only pass to free what was returned from malloc.
In this case, you make one allocation for an array of char *, so you do a single free to clean it up. Also, the amount of space you're allocating is 10 * sizeof(Node), but it should be 10 * sizeof(char *).
That depends on where those pointers came from, and who owns them.
If they were dynamically allocated and the node owns them, then you should free them before freeing the array.
If they were dynamically allocated but owned elsewhere, their respective owners should free them later.
If they were not dynamically allocated, you mustn't free them at all.
If you have a combination of the three, you're in trouble.
You should also allocate it with sizeof(char*), or sizeof(*head->word_ptrs), not sizeof(Node).
Although, if the size is always ten, you might as well use an array:
typedef struct node{
char *word_ptrs[10];
int value;
struct node *next;
} Node;

Structures and pointers in C [duplicate]

This question already has answers here:
Returning a struct pointer
(6 answers)
returning a local variable from function in C [duplicate]
(4 answers)
Closed 8 years ago.
I'm creating a structure inside a function and then returning its pointer. For some reason I keep getting the same memory address each time.
typedef struct list_type
{
node_t *head;
node_t *tail;
} list_t;
list_t newList() {
list_t list = {NULL, NULL};
list_t *listptr = &list;
printf("newList: %p\n", listptr);
return listptr;
}
Outputs:
newList: 0x7fffb42c8ae0
newList: 0x7fffb42c8ae0
newList: 0x7fffb42c8ae0
What am I doing?...
You are allocating list on the stack, but you're trying to return a reference to it from a function. This is a big no-no in C, since the struct's memory is automatically freed by the compiler when it goes out of scope. If you want memory to persist beyond the scope it is allocated in, you need to use malloc.
Furthermore, list_t and a pointer to it (list_t*) are two different types, and you need to indicate that as such in your function definition.
list_t* newList() {
list_t *listptr = malloc(sizeof(list_t));
printf("newList: %p\n", listptr);
return listptr;
}
However, be careful when using malloc. Since you're allocating memory manually, you'll now need to ensure that you call free on the pointer when you're done with it, or it will leak, since the compiler cannot free the memory for you.
list_t list = {NULL, NULL};
allocates memory on stack. Memory allocated on stack is automatically freed when the variable, list in your case, goes out of scope.
That is why you are getting the same address again and again as memory allocated to list on stack gets freed when program comes out of function newList() and is available for allocation. And, when you call the newList() again, same memory is alloacted again.
You should read about different memory allocations and pay more attention to the compiler warnings.
You're returning a pointer to an object allocated on the stack. If you use the value that the pointer points to in the function that calls newList(), you'll cause undefined behavior to occur.
You should read about malloc() and free().
Your function returns a list_t, a structure type, which is perfectly fine by-value. I see no evidence you're trying to dynamically allocate a list_t, and no evidence you even need to do so.
Lose the pointer stuff for this specific structure type entirely and just do this:
list_t newList()
{
list_t list = {NULL, NULL};
return list;
}
void freeList(list_t lst)
{
// TODO: delete lst nodes by walking lst.head through lst.tail
}
int main()
{
list_t lst = newList();
...
freeList(lst);
}
Don't step into the arena of managing dynamic memory because you can; do it when you need to do so, and in this case, you don't. You obviously need to in order to manage the actual list nodes, but thats a different issue than this one.

How can I free up n bytes of memory in C?

I wanted to create a generic Linked List in C. Following is the structure of the node:
typedef struct node {
void *value;
int size; // n bytes
ind index; // index of the node
struct node *next;
} Node;
And my delete_node function is as following. The search function sends a pointer to the Node I want to delete.
Node *search_list(Node *list, void *data, int n_bytes);
int delete_node(Node *list, Node *to_be_deleted); // returns 1 on success
Inside the delete_node function I want to free up the memory pointed by void *value and then free up the memory allocated for the Node itself.
free(to_be_deleted->value); // Would this work??
free(to_be_deleted);
Since it is void pointer we don't know that how many bytes the object it is pointing to has occupied. How can we free up the memory for that?
Sorry if it is a stupid questions?
The memory allocator keeps track of how large memory allocations are on its own -- there's no need to tell free() how much memory to free.
As such, you should be able to just get rid of size and n_bits.
free(to_be_deleted->value); // Would this work??
Straight forward answer , Yes this will work.
simple thing :
see the definitions of free() and malloc()
void free(void *) // free takes void* as argument so it will work
void* malloc(sizeof(type))
In mallocwe have to pass thesize that how many bytes we want to allocate.
but in free just pass the pointer and whatever bytes allocated to that pointer on heap storage it will be freed
Yes, what you wrote should work. The reason is that malloc (which is a library call) creates metadata that is used to determine which parts of memory are free and which ones are taken. When you call free(), you are actually only modifying this metadata such that subsequent calls to malloc know that this memory can be re-used (note that most implementations will not zero the existing data).

Freeing struct with pointer and non-pointer variables

I'm trying to implement linked-lists with c struct, I use malloc to allocate a new node then allocate space for value, so I've been thinking how to free the structure once I'm done with them, my structure looks like this:
typedef struct llist {
char *value;
int line;
struct llist *next;
} List;
I have a function that walks through the struct and free its members like this:
free(s->value);
free(s);
My question is, does that also free the int line?
Yes.
The int line is part of the structure, and so gets freed when you free the structure. The same is true of the char *value. However, this does not free the memory which value points at, which is why you need to call free separately for that.
Yes it does. When you allocated memory for s it allocated memory for these three:
pointer to a char (value)
integer (line)
pointer to a struct llist (next)
When you freed s, all that storage went away (which includes memory for line).

Resources