How to free char array in struct - c

I see that you can free char * pointers within struct but how do you free char[N] inside a struct
typedef struct Edge
{
char number[13];
int numOfCalls;
struct Edge *next;
} Edge;
When I do this i get an error
Edge *edge = malloc(sizeof(Edge));
edge->next = NULL;
strcpy(edge->number,numberOne); // numberOne is also a char[13];
free(edge->number);
free(edge);

If you use char array (char number[13]) in struct, you don't have to malloc or free the array. Once you do malloc for struct Edge, there is also space for number in memory.
In summary, if you use char pointer as a member of struct Edge, you need to malloc or free memory space for char pointer, but you don't have to do that in your case. Therefore, delete free(edge->number) line.

The lifespan of number in the struct Edge is automatic. Even if you dynamically allocate an Edge struct, when you free the struct, you'll free the memory for the char array.

Related

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;

Allocating memory for structures in c

struct data{
char *key;
char *fname;
char *lname;
char *grade;
struct data *next;
};
newnode = (struct data*)malloc(sizeof(struct data));
strcpy(newnode->lname,lname);
strcpy(newnode->grade,grade);
strcpy(newnode->key,key);
strcpy(newnode->fname,fname);
newnode->next=NULL;
So i was working on hashtables. The above code crashes while
struct data *newnode;
newnode = (struct data*)malloc(sizeof(struct data));
newnode->lname=(char*)malloc(strlen(lname)+1);
newnode->fname=(char*)malloc(strlen(fname)+1);
newnode->grade=(char*)malloc(strlen(grade)+1);
newnode->key=(char*)malloc(strlen(key)+1);
strcpy(newnode->lname,lname);
strcpy(newnode->grade,grade);
strcpy(newnode->key,key);
strcpy(newnode->fname,fname);
newnode->next=NULL;
this code seems to run. Why is that? As far as i understand i've already allocated memory for my struct in the heap. Why would i have to do it for each object specifically? Is there something else im missing? Cause i really don't understand why the bottom example would work.
With newnode = (struct data*)malloc(sizeof(struct data)), you allocate memory only for struct data, which is a set of pointers, but you do not allocate any memory for that where these pointers are pointing to and where you will copy your strings to. So you have to allocate memory for each string separately, either by using malloc as in the second part of your question, or by using strdup, which does malloc and strcpy in one command:
struct data{
char *key;
char *fname;
char *lname;
char *grade;
struct data *next;
};
newnode = (struct data*)malloc(sizeof(struct data));
newnode->lname = strdup(lname);
newnode-> grade = strdup(grade);
newnode-> key = strdup(key);
newnode-> fname = strdup(fname);
newnode->next=NULL;
It's worth noting that strdup requires a string as input, i.e. a pointer that is not NULL and that points to a \0-terminated sequence of characters.
When you do
newnode = malloc(sizeof(struct data));
you only allocate memory for the actual structure. But since the structure contains pointers, you need to make those pointers point somewhere valid. The single malloc call doesn't know anything about the contents of the structure, or how much extra memory it should allocate for all the pointers.
If, for example, you declare a single normal pointer variable you would not expect to be able to just use it as a destination for a strcpy call without allocating memory, would you?
When you malloc a structure with char * inside it doesn't point anywhere (at least is NULL) so you've to malloc it as a normal sequence of characters also because you must know the size of the destination string. You can do it in your way using malloc and strcpy or just strdup.

Freeing array of structs inside struct

I have two structs
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
As you can see, there is pointer to first obj_t inside cluster_t
What I want to do is to free every obj_t from array inside cluster_t
Do I have to write it with for loop like this?
void clear_cluster(struct cluster_t *c)
{
for(int i = 0; i<c->size;i++)
{
free(&c->obj[i]);
}
free(c->obj);
}
Or is it ok to free the memory just like this ?
void clear_cluster(struct cluster_t *c)
{
free(c->obj);
}
There should be one free() for every malloc() you have, and executed in the opposite order from which it was allocated.
The field obj of cluster_t is a pointer to an array of object_t. This is probably allocated with one malloc() when initializing your cluster_t (something like c->obj = malloc(c->capacity*sizeof(*c->obj))), so it only needs to be freed with one call to free(). You would then want to free the cluster_t allocation itself (assuming it too was dynamically allocated):
free(c->obj);
free(c);
There would be a difference, however, if each object_t itself had a dynamic allocation within it. (In your example, object_t does not.) In that case, you would have needed to iterate through the array and malloc() an allocation when you created the array, and therefore do the reverse and free() each at the end.
It depends on how you allocated. It seems you did something like
struct cluster_t cluster;
cluster.obj = malloc(sizeof (struct obj_t) * SOMENUMBER);
in this case, cluster.obj is just a pointer to an array. All you need to do is
free(cluster.obj)
or
free(c->obj)
in that function which receives a pointer to c.
You only have to iterate over the array calling free if you have an array of pointers.
Remember that & takes the memory address of the variable. You don't free the pointer, you free the memory that the pointer points to. You will never do something like free(&pointer).

Confused by malloc and free behaviour

I am confused with the usage of free() in regard to data structures in C.
If I have the following data structure:
struct Person {
char *name;
int age;
float weight;
float height;
};
I am allocating memory for the structure via malloc(), likewise: struct Person *me = malloc(sizeof(struct Person));
After I am done with using my structure (right before ending the program), I proceed to freeing the memory allocated, like this:
free(person_pointer->name);
free(person_pointer);
Freeing the memory that the name pointer points to is necessary to my knowledge, because if I only free person_pointer I only free the memory that was allocated to store the data structure and its members but not the memory that is pointed to by pointers-members of the structure.
However with my implementation valgrind seems to suggest that the first free() is invalid.
So my question boils down to: When I free the memory that a struct occupies via a pointer, should I preemptively free the memory that member pointers point to or not?
EDIT: This is my whole code:
#include <stdio.h>
#include <stdlib.h>
struct Person {
char *name;
int age;
float weight;
float height;
};
int main(int argc, char **argv)
{
struct Person *me = malloc(sizeof(struct Person));
me->name = "Fotis";
me->age = 20;
me->height = 1.75;
me->weight = 75;
printf("My name is %s and I am %d years old.\n", me->name, me->age);
printf("I am %f meters tall and I weight %f kgs\n", me->height, me->weight);
free(me->name);
free(me);
return 0;
}
me->name = "Fotis";
/* ... */
free(me->name);
The rule is:
1 malloc = 1 free
You didn't use malloc on me->name, so you don't have to free it.
BTW, me->name should be of const char * type.
When you do
me->name = "Fotis";
The name pointer is not alloced by malloc, it points to a stack variable which is stored in the strings table of your binary file at compile time, hence you can't free it.
The rule of thumb is : Only free what you have malloced.
You can't update this read-only string though.
If you did something like :
me->name = strdup("Fotis");
Since strdup does a malloc (see the manual), you have to free it, and you can update the string after its creation.
Yes you have to free all the memory of pointers inside the structure if you allocated them.
Also make sure you free the members before you free the structure.
A simple way to remember is free them in the reverse order in which you have allocated.
The problem is that you didn't actually malloc'ed the char * name inside your structure.
struct Person *me = malloc(sizeof(struct Person));
me->name = strdup("Fotis");
...
free(me->name);
free(me);
return (0);
When you write this
me->name = "Fotis";
You don't actually malloc, the pointer name points to a stack variable of type const char *, wich is not malloc'ed.

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