Confused by malloc and free behaviour - c

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.

Related

Does malloc assigns memory to custom struct's properties?

I've been working on some C projects and was wondering if I create a custom structure, for example, Student, define a variable of the custom structure type, and allocate memory to it using malloc, does it also allocate memory for variables' properties separately or are they all kept in the same space? if yes, will there be any difference if I allocate memory using malloc separately for every property?
For example:
typedef struct {
unsigned int ID;
char *first_name;
char *last_name;
int num_grades;
float *grades;
unsigned short int days_absent;
char *memo;
} Student;
int main() {
// Declare students array
Student *students = NULL;
int students_size = 0;
// Allocate memory for students array
students = (Student *) malloc(sizeof(Student));
return 0;
}
That allocates enough memory for the struct, which includes enough memory for ID, first_name, etc and all padding requirements.
Note that while it allocates memory for the pointer first_name, it doesn't allocate a buffer to hold the name. It just allocates memory for first_name, a pointer. If you want memory in which to store the names, you will need to allocate it.
If the struct had a char first_name[40]; field, it would be a different story. To allocate enough memory for first_name, it needs to allocate enough memory for an array of 40 char instead of enough for a pointer. This does provide a space in which a string could be stored.
No, it doesn't. It allocates uninitialized memory for the number of chars you want - which is usually a calculation based on sizeofs.
If you want it to allocate memory to store values that your struct has pointers to, you'll have to add that after having allocated the memory for the struct.
You'll also have to "go backwards" when you free such a struct.
Example:
typedef struct {
char *data;
} foo;
foo *foo_create() {
foo *retval = malloc(sizeof *retval ); // try allocation
if(retval == NULL) return NULL; // check that it worked
retval->data = malloc(10) ; // allocate something for a member
if(retval->data == NULL) { // check that it worked
free(retval); // oh, it didn't, free what you allocated
return NULL; // and return something to indicate failure
}
return retval; // all successful
}
void foo_free(foo *elem) {
if(elem != NULL) { // just a precaution
free(elem->data); // free the member's memory
free(elem); // then the memory for the object
}
}
Does it also allocate memory for variables' properties separately
No. After allocating for students, allocate for students->first_name, students->last_name, etc.
does it also allocate memory for variables' properties separately or are they all kept in the same space?
No. malloc() is given a size to indicate how much contiguous memory to allocate, and it returns a pointer pointing to it... malloc() knows nothing about what you are going to do with the pointer. When you assign it to a pointer variable to Student type is, somehow, dressing a bunch of memory with structure. But the char * fields that you have defined inside (or if you have other fields pointing to other structured data) those have to be allocated separately (or ask for more memory to allocate them all in the same returned segment, but this requires practice and knowledge of the alignment issues that arise from it)

Free in a structure element

Hello I have a question regarding malloc and free type of things.
suppose I have a structure with another structure inside it
typedef struct All{
int number;
} A;
typedef struct Bet{
A *point;
} B;
Then I create a B.
B* first = malloc(sizeof(B));
first->point=malloc(sizeof(A));
Now lets say I want to make a function that deletes the struct B entirely.
For the delete function I know we have to use
free(first);
So do I also have to free(first->point) or will it disappear automatically if i do free(first);
I want to add more to what #thisisbenmanley said and build an actual explination that will also show how to wrap part of the code you write.
The basics
I'll cover just malloc() and free() here. Whenever you call malloc() there should be a free() also. Let's take this example with a simple int.
int *p = malloc(sizeof(int));
*p = 5;
printf("%d", *p);
free(p);
It is the same for a struct. Another example:
typedef struct Person
{
int Age;
int Height;
}Person;
Person* p = malloc(sizeof(Person));
p->Age = 20;
p->Height = 185;
// do something with it ...
free(p);
Another very important thing you have to know: malloc() can return NULL if the allocation fails. It actually means that there is no space to allocate the block. It is very important to actually check for it. For example:
int* v = malloc(sizeof(int)*999999999);
if (v == NULL)
{
printf("Allocation failed.");
return -1;
}
// Allocation successfull. Do something with the vector ...
Structures in structures and structures with pointers
If structures do not contain pointers just free() will do the job. Example:
typedef struct Point
{
int x;
int y;
}Point;
typedef struct Line
{
Point a;
Point b;
}Line;
// this will allocate actually 4 ints
Line* p = malloc(sizeof(Line));
// this is how you access each point's coordinates.
p->a.x;
// do something ...
// this will free both points (the 4 ints)
free(p);
Now this is where code can get very unclear depending on each situation. If a structure contains one or more pointers if might prove difficult to keep the code simple to read. Suppose the following struct:
typedef struct Person
{
int Age;
int Height;
char* FName;
char* LName;
char* Address;
}Person;
If you want to allocate a Person you need 4 malloc() calls. If you also add error checking it will be quite voluminous. Definetly this should be wrapped inside a function:
Person* AllocPerson()
{
// i'm skipping it now so that my point is clear, but checking
// if malloc returned NULL is recommended
Person* p = malloc(sizeof(Person));
p->FName = malloc(sizeof(char)*30);
p->LName = malloc(sizeof(char)*30);
p->Address = malloc(sizeof(char)*40);
return p;
}
Now whenever you need a Person you can just Person* p = AllocPerson();. Same goes with a FreePerson() function which will take 4 free() calls so that after you finished working with the struct, you simply call FreePerson(p).
void FreePerson(Person* p)
{
free(p->FName);
free(p->LName);
free(p->Address);
free(p);
}
You can evolve the AllocPerson function even further and turn it into a Create function:
Person* CreatePerson(int Age, int Height, char* FirstName, char* LastName, char* Address)
{
// i'm skipping it now so that my point is clear, but checking
// if malloc returned NULL is recommended
Person* p = malloc(sizeof(Person));
p->FName = malloc(sizeof(char)*30);
p->LName = malloc(sizeof(char)*30);
p->Address = malloc(sizeof(char)*40);
p->Age = Age;
p->Height = Height;
strcpy(p->FName, FirstName);
strcpy(p->LName, LastName);
strcpy(p->Address, Address);
return p;
}
Now you can just do this whenever you need a person:
Person* p = CreatePerson(20, 180, "Alex", "Boris", "Street nr. 5");
The CreatePerson() function both allocates and initialises fields of a Person instance. This aproach of making a Create and Delete function to a structure is widely used in C, especially when you have to use an already made API.
Important notes
Always free() memory even though after exiting main() your OS will take care of the blocks still allocated. This is considered good practice.
Try to use dynamic memory as less as possible. The Heap is slower than the Stack!
Try to reuse allocated space whenever possible. Allocating and Freeing are expensive operations!
You would also have to free(first->point). When you free(first), all that will deallocate is the bytes holding the struct first, which only holds a pointer. That alone will not touch the actual memory address pointed to by point; free(first->point) beforehand would cover that.

Understanding dynamic memory allocation of a string within a struct

I have come across an instance where memory is allocated dynamically to a char pointer within a struct in a way that does not make much sense to me, but - of course - works.
A similar question has been posted before. The answers, however, did not help me understand what is actually happening in the allocation process.
Here is the code example I found:
struct a_structure {
char *str;
struct a_structure *next;
};
Memory has been allocated in the following way:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
...
char *some_words="How does this work?";
ptr_start->str=(char *)malloc(strlen(some_words)+1);
strcpy(ptr_start->str, some_words);
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
...
I don't understand why malloc is used with the size of a pointer here. ptr_start is a pointer of type struct a_structure. That would mean it needs memory of size sizeof(struct a_structure) + the size of my string that hasn't been specified in the structure declaration. In the above example, however, malloc returns the address of yet another pointer pointing to a structure of type a_structure, am I right?
I don't understand why malloc is used with the size of a pointer here.
ptr_start is a pointer of type struct a_structure. That would mean it
needs memory of size sizeof(struct a_structure) + the size of my
string that hasn't been specified in the structure declaration
You are right. To create structure a_structure in order to manipulate it we need to allocate memory for whole structure.
(Unless the object has been ALREADY created and for whatever reason we need a dynamically allocated pointer holding pointer to that object).
but - of course - works.
The presented fragment of the program cannot work properly for the stated above reasons.
In the above example, however, malloc returns the address of yet
another pointer pointing to a structure of type a_structure, am I
right?
Yes, you are right.
This is also problematic:
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
ptr_start->next can hold a pointer already. We typically do not need to allocate a pointer here. We would assign a pointer to the existing
structure or we would allocate memory for the whole structure.
See example:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct a_structure {
char *str;
struct a_structure *next;
};
struct a_structure * allocatePointer(void)
{
// ptr ptrToObj1Allocated points to allocted memory which can hold a ponter
struct a_structure * ptrToObj1Allocated = malloc(sizeof (struct a_structure *));
return ptrToObj1Allocated;
}
int main(){
// 1.
struct a_structure obj1; // structure a_structure has been allocated on the stack
struct a_structure * ptrToObj1 = & obj1; // points to the existing structure
char *some_words = "How does this work?";
ptrToObj1->str = malloc(strlen(some_words)+1);
if(ptrToObj1->str == NULL){printf("No enough memory\n"); return -1;}
strcpy(ptrToObj1->str, some_words); // copy the string
// now obj1 has its own copy of the string.
// 2.
// dynamically allocate another structure on the heap
// we want to allocate memory for the structure not just a memory to keep the pointer to the structure.
struct a_structure *obj2 = malloc( sizeof (struct a_structure)); // memory has been allocated to hold struct a_structure with 2 pointers
if(obj2 == NULL){printf("No enough memory\n"); return -2;}
char *words = "More words..";
obj2->str = malloc(strlen(words)+1);
if(obj2->str == NULL){printf("No enough memory\n"); return -3;}
strcpy(obj2->str, words); // copy the string
obj2->next = ptrToObj1; // points to the already existing object
//----
printf("String in obj1 is: %s\n", ptrToObj1->str);
printf("String in obj2 is: %s\n", obj2->str);
printf("obj2->next points to structure with string: %s\n", obj2->next->str );
// free the allocated memory:
free(ptrToObj1->str);
free(obj2->str);
free(obj2);
return 0;
}
Output:
String in obj1 is: How does this work?
String in obj2 is: More words..
obj2->next points to structure with string: How does this work?
Given that you have struct a_structure* ptr_start, this code is incorrect and does not work:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
It should have been:
ptr_start = malloc(sizeof *ptr_start);
The reason why it "seems to work" is because you invoked undefined behavior, and anything can happen. The program could seem to work one moment, then crash at another time.
This does however just allocate the struct itself. The pointers inside it will, like all pointers, point at memory allocated somewhere else. The following code with malloc for the string and strcpy() is one way to do so.
The last line is however incorrect for the same reason as pointed out above.

Usage of strdup()

Let's say we have a struct :
struct Person {
char *name;
};
struct Person *Person_create(char *name){
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who->name = strdup(name);
return who;
}
void Person_destroy(struct Person *who){
assert(who != NULL);
free(who->name);
free(who);
}
And the main function :
int main(int argc,char *argv[]){
struct Person *mike = Person_create("mike");
Person_print(mike);
Person_destroy(mike);
return 0;
}
The above code won't work properly without the strdup() function. Valgrind says that the address you try to free with free(who->name) is not malloc'd. What's the story behind this, didn't I malloc'd that memory when I malloc'd the struct? And what difference does the strdup() make?
In your code each Person object involves two independent blocks of memory: the struct Person object itself and the separate memory block for the name. That separate memory block is pointed by the name pointer inside the struct. When you allocate struct Person by using malloc, you are not allocating any memory for the name. It is, again, an independent block of memory that should be allocated independently.
How you are planning to allocate memory for the name is entirely up to you. If you use strdup (which is essentially a wrapper for malloc) as in your code above, then you will have to free it by free in the end.
You did not explain what you mean by "without the strdup() function". What did you code look like without it? If you simply did
who->name = name;
then you made that who->name pointer to point directly to the string literal memory occupied by literal "mike". String literals reside in static memory. You are not allowed to free them. This is what valgrind is telling you.
Mallocing the struct allocates memory for the pointer name but it doesn't allocate any memory for name to point to. At that point who->name will be some random garbage value so freeing it makes no sense.
strdup uses malloc internally to allocate memory for the string it copies. Once you've got a pointer back from strdup you can, and should, free it when you're done.
strdup do noes call malloc, it is only string operation. you only malloc the pointer to the struct ,not the inner member

Problem when typecasting a void * pointer used inside a structure to an int * pointer!

My code is as follows,
#include<stdio.h>
struct data
{
int a ;
void *b;
};
int main()
{
struct data *d;
int *ptr;
int key=10000;
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
}
And i get a segmentation fault!! Any idea why?? Thanks in advance for any help
struct data *d merely declares a pointer. You have not allocated this struct anywhere. You need to either malloc it or declare it just as struct data d on the stack or globally.
The former can be done like this:
d = malloc(sizeof(struct data));
If you choose the latter, accessing b has to be written as d.b.
You are not allocating any memory for d. It likely points to an invalid memory area and so - segmentation fault.
You can solve this like so:
struct data *d = malloc(sizeof(*d));
You are getting segmentation fault at the line d->b=&key; Note that you have not allocated any memory location to the structure variable d. So d contains some garbage value, and d->b it trying to use that garbage address to dereference the pointer and get the component b. Here is where you get the segfault. Either statically allocate the struct variable, or use malloc to dynamically allocate it.
int main()
{
struct data *d;
int *ptr;
/* Here you are allocating memory to the
* pointer variable, which will be used to
* point to the structure type data
*/
d = malloc (sizeof (struct data));
int key=10000;
/* Now you can dereference the pointer
* and get any of the components of the
* structure, because 'd' contains a valid
* address.
*/
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
/* Good practice to free the memory location
* you have allocated. Not freeing will lead to
* memory leak in larger applications. After you
* free the memory location denoted by the address
* stored in 'd', you will not be anymore access
* the contents of it.
*/
free (d);
/* d->b; or d->a; is no more possible at this point
* as we have freed the memory pointed by 'd'
*/
}
Or you can use:
int main()
{
/* Not a pointer, statically allocated */
struct data d;
int *ptr;
int key=10000;
d.b=&key;
ptr=(int *)d.b;
printf("%d\n",*ptr);
}
So, it is not the typecasting of void * to int * that causes the segfault. Its the illegal memory reference of the pointer variable which you have used but not allocated/initialized.
The problem is that you didn't allocate memory for a d pointer: struct data *d;. This lines only creates a pointer, it doesn't alloc memory for it. Please try the following code:
int main()
{
struct data *d = (struct data*)malloc(sizeof(struct data));
int *ptr;
int key=10000;
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
free(d);
}

Resources