How to free() an array of structs allocated by malloc()? - c

I've been working on a project that uses structs as storage for strings. I declared a struct consists of char type members:
struct datastore1
{
char name[50];
char address[50];
char email[50];
char number[50];
char idnum[50];
};
I'm aware that I can just do char *name, char *address... but let's say we specified it with max length of 50. Then on my function which uses the struct, I malloc'ed it with index size of 30:
struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));
Supposedly I finished copying all strings into the struct by accessing each index, How should i free the allocated memory that was used after calling malloc? I tried doing free(dsdata) on the end of the program but I am not sure if it's the right way. Should i free each indexes individually? Please enlighten me. Thank you in advance for the feedback!

How should i free the allocated memory that was used after calling malloc?
Consider below example,
struct datastore1 *obj1 = malloc(sizeof(struct datastore1));
free(obj1);
Here obj1 is pointing to the block of memory of size same as size of datastore1 in order to free you need to send the address which is allocated by malloc.
likewise,
struct datastore1 *obj2 = malloc(3 * sizeof(struct datastore1));
free(obj2);
obj2 is pointing to a block of contiguous memory of size 3 * sizeof(datastore1) you need to pass the base address to free
Should i free each indexes individually?
NO, Since block of memory is allocated only once and you need to free exactly one time.
Let me extend it further,
struct datastore1 *obj3[3];
for(int i=0;i<3;i++)
obj3[i] = malloc(sizeof(struct datastore1));
for(int i=0;i<3;i++)
free(obj3[i]);
Here obj3 is array of pointer and each index is pointing to different part of memory and hence need to be freed individually.
Note: For simplicity I haven't considered return value from malloc. Null check has to be done on malloc return value.

1.
How should I free the allocated memory that was used after calling malloc?
I tried doing free(dsdata) on the end of the program but I am not sure if it's the right way.
free(dsdata) is fine, since you allocated the whole space by just one call to malloc with:
struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));
To cite the standard (C18), 7.22.3.4 - "The malloc function" (emphasize mine):
7.22.3.4 The malloc function
Synopsis
1
#include <stdlib.h>
void* malloc(size_t size);
Description
2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
Returns
3 The malloc function returns either a null pointer or a pointer to the allocated space.
It is correct to use free(dsdata) because malloc allocated all of the required space at once and returned a pointer to the first structure variable of this array which is assigned to the pointer of dsdata.
The free() function "knows" that dsdata is a reference to the whole allocated space. You do not need to free each of the 30 structures of type struct datastore1 in memory individually.
2.
Should I free each indexes individually?
No, you do not need and even more important you should not do so; this would be Undefined Behavior:
Citation from the current standard (C18), 7.22.3.5/3 - "The free function" (emphasize mine):
Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

As far as I understand you only used malloc to allocate space for an array of datastore1 struct, so it is sufficient to just do free(dsdata).
If in the struct you would have pointers and you would use malloc to allocate each of them, only than you would need to free each of them first.

Both answers above are correct, but to fully understand how does it work I recommend you to learn how to use valgrind.
To check if program released memory correctly use
valgrind -v --leak-check=full --track-origins=yes ./your-program
This will execute your program on valgrind's virtual processor and give you full feedback about used resources.
Basically operator [] in C programming language in array definition context causes creation of (lets say to simplify) static array - this means that array is included in size of structure (if defined as part of structure) or is stored on the stack (if defined in function or globally).
The malloc function returns address of block of data you can use. Size of this block is at least as big as you requested. When you use free you release this block wich in this case means all data in block pointed by this address will be released.

Related

do I need to allocate space for pointer as well as space for memory area whose address will be kept in pointer in pointer to pointer and realloc

I have this code
int main(int argc, char *argv[])
{
int i=1;
char **m=malloc(sizeof(char *)*i);
printf("%zu\n",sizeof *m);
m[0]=malloc(strlen("hello")+1);
strcpy(m[0],"hello");
printf("%s\n", m[0]);
i=2;
m=(char **)realloc(m,sizeof (char *)*i);
m[1]=malloc(strlen("hi")+1);
strcpy(m[1],"hi");
printf("%s %s \n",m[0],m[1] );
// TODO: write proper cleanup code just for good habits.
return 0;
}
this is how I am allocating pointer char **m 8 byte single char pointer
int i=1;
char **m=malloc(sizeof(char *)*i);
and this is how I am allocating area of space whose address will be kept in m[0]
m[0]=malloc(strlen("hello")+1);
strcpy(m[0],"hello");
printf("%s\n", m[0]);
I like to know is this normally how its done. I mean allocating space for pointer and then allocating space in memory that the pointer will hold.
Does m[0]=malloc(strlen("hello")+1); is same as this *(m+0)=malloc(strlen("hello")+1); and does this m[1]=malloc(strlen("hi")+1); this *(m+1)=malloc(strlen("hi")+1);
And I am increasing pointer to pointer numbers like this in allocation m=(char **)realloc(m,sizeof (char *)*i); before m[1]=malloc(strlen("hi")+1);
is there anything wrong with above code. I seen similar code on this Dynamic memory/realloc string array
can anyone please explain with this statement char **m=malloc(sizeof(char *)*i); I am allocating 8 byte single pointer of type char but with this statement m=(char **)realloc(m,sizeof (char *)*i); why I am not getting stack smaching detected error. How exactly realloc works. can anyone give me the link of realloc function or explain a bit on this please
I like to know is this normally how its done. I mean allocating space for pointer and then allocating space in memory that the pointer will hold.
It depends on what you are trying to achieve. If you wish to allocate an unspecified amount of strings with individual lengths, then your code is pretty much the correct way to do it.
If you wish to have a fixed amount of strings with individual lengths, you could just do char* arr [n]; and then only malloc each arr[i].
Or if you wish to have a fixed amount of strings with a fixed maximum length, you could use a 2D array of characters, char arr [x][y];, and no malloc at all.
Does m[0]=malloc(strlen("hello")+1); is same as this *(m+0)=malloc(strlen("hello")+1);
Yes, m[0] is 100% equivalent to *((m)+(0)). See Do pointers support "array style indexing"?
is there anything wrong with above code
Not really, except stylistic and performance issues. It could optionally be rewritten like this:
char** m = malloc(sizeof(*m) * i); // subjective style change
m[0]=malloc(sizeof("hello")); // compile-time calculation, better performance
why I am not getting stack smaching detected error
Why would you get that? The only thing stored on the stack here is the char** itself. The rest is stored on the heap.
How exactly realloc works. can anyone give me the link of realloc function or explain a bit on this please
It works pretty much as you've used it, though pedantically you should not store the result in the same pointer as the one passed, in case realloc fails and you wish to continue using the old data. That's a very minor remark though, since in case realloc fails, it either means that you made an unrealistic request for memory, or that the RAM on your system is toast and you will unlikely be able to continue execution anyway.
The canonical documentation for realloc would be the C standard C17 7.22.3.5:
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. The contents of the new
object shall be the same as that of the old object prior to deallocation, up to the lesser of
the new and old sizes. Any bytes in the new object beyond the size of the old object have
indeterminate values.
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Returns
The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.
Notably there is no guarantee that the returned pointer always has the same value as the old pointer, so correct use would be:
char* tmp = realloc(arr, size);
if(tmp == NULL)
{
/* error handling */
}
arr = tmp;
(Where tmp has the same type as arr.)
Your code looks fine to me. Yes, if you are storing an array of strings, and you don't know how many strings will be in the array in advance, then it is perfectly fine to allocate space for an array of pointers with malloc. You also need to somehow get memory for the strings themselves, and it is perfectly fine for each string to be allocated with its own malloc call.
The line you wrote to use realloc is fine; it expands the memory area you've allocated for pointers so that it now has the capacity to hold 2 pointers, instead of just 1. When the realloc function does this, it might need to move the memory allocation to a different address, so that is why you have to overwrite m as you did. There is no stack smashing going on here. Also, please note that pointers are not 8 bytes on every platform; that's why it was wise of you to write sizeof(char *) instead of 8.
To find more documentation about realloc, you can look in the C++ standard, or the POSIX standard, but perhaps the most appropriate place for this question is the C standard, which documents realloc on page 314.

C - How to use free() to free a struct in memory?

I need some help to deallocate memory for a struct.
I'm storing a pointer to a memory location in a variable but I want to deallocate the memory after use. However, when I try to deallocate the memory it only deallocates the first structure item (name) and age remains in memory. My code can be seen below.
int main(int argc, char **argv)
{
struct employee {
char *name;
int age;
};
// Make pointer, employee struct and put struct in memory at pointer location
struct employee *employee_1;
struct employee new_employee;
new_employee.name = "Sue";
new_employee.age = 26;
employee_1 = (struct employee *) malloc(sizeof(new_employee));
(*employee_1).name = new_employee.name;
(*employee_1).age = new_employee.age;
// ... Some operations done
// Deallocate memory location
free(employee_1);
return 0;
}
Both the name and age of the employee are definitely being stored at the memory location, but I can't deallocate them both. I have tested this to have more than two items in the struct and each time it's only the first item that is deallocated.
I have tried a few different methods like deallocating each individually in case that would work free((*employee_1).name) but this throws an error. Any help would be appreciated.
No, you don't deallocate age yourself. That is not a "pointer returned by malloc() and family", so you don't need to (call) free() on that.
Quoting C11, chapter ยง7.22.3.3, (emphasis mine)
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
Also, FWIW, free() takes a pointer, so even passing the address of age member variable will also be wrong. The allocated memory will be automatically deallocated by the OS or memory manager, once the program terminates.
To sum up, you should only call free() with pointers returned by memory management functions (i.e, malloc() and family), that's it. Other pointers, even if they are pointers, if not allocated memory via memory management functions, (i.e, does snot store a pointer returned by malloc() and family) need not to be free()-d.
For example, in your case, you do not call free() on (*employee_1).name (rather , use employee_1->name, gives better readability, IMHO), as the pointer is not returned by memory management functions. Doing so will invoke undefined behavior.
That said, please see this discussion on why not to cast the return value of malloc() and family in C..

Why does free() need the starting pointer of a dynamic array?

If I run this code it will crash with a stack dump:
int * a = (int *) malloc(sizeof(int) * 10);
a++;
free(a);
Why doesn't it work?
Why does it need the pointer returned by malloc()?
What records does the resource management system behind it keep?
Is it the length of the array? Is it the last cell's address? And does it associate it with the starting pointer?
When memory is allocated, the size of allocated memory is stored in a block adjacent to the allocated block.
Why doesn't it work?
int * a = (int *) malloc(sizeof(int) * 10);
a++;
free(a);
This will not work because, free searchs for the adjacent block which has the size of allocated memory.
Why does it need the pointer returned by malloc?
The adjecent block of pointer returned by malloc, has the information about the size of allocated memory.
It doesn't work because you add one to the pointer that malloc returned to you.
free expects a pointer that malloc returned. Due to the a++ the pointer is no longer what malloc returned and thus free doesn't know what to do with it.
The malloc function reserves a little bit more memory in the heap than what the user tells it. This is because a unique value before the allocated blocks is saved in order to know what size and chunks of memory the system is able to free.
int * a = (int *) malloc(sizeof(int) * 10);
When you increment the pointer "a", the system will refer to the new location that a is pointing to and therefore it results in reading garbage data.
This leads to usually undefined behavior and usually causes crashing when running your program.
Malloc usually allocates more data than what we usually request. This additional space is used to house some of the important information such as the amount of memory(number of bytes) allocated when a malloc call is made. Sometimes additional information such as pointer to the next free location is also maintained. This information is stored at a specific location relative to the starting memory location that malloc return to us. If we return some other address to the free function, then it will look at the value in the address relative to what you passed to free and will end up freeing that number of bytes and "may" cause a crash.

Memory is not reallocating

I'm in the middle of a project and I'm trying to use malloc() and realloc(). I know when I malloc, it works, but when I use realloc, it doesn't change the amount of alloced memory at all. I've always though that realloc will re-allocate your already malloced memory.
Here is what I have:
This include:
#include <stdlib.h>
I have a struct:
struct student {
int age;
int numOfClasses;
int gender; //0 male; 1 female
} student;
When I want to make 7 of those structs using malloc, I will use this line of code:
student stud* = (structure*) malloc(7*sizeof(student));
This line works. That line of code takes the size of the structure and multiples that by 7. In short, this will grab enough memory to make an array of 7 structures.
Now, if I want to change that to 8, I would do this where A is the previous malloced memory, and B is the new malloced (or realloced) memory:
Here is how I have it in code:
stud = (student*)realloc(stud, 8*sizeof(student));
From what I know, realloc takes the variable in the second parameter and mallocs that amount of memory. Then, it takes the pointer (or previous malloced), and fills in the just malloced memory with as much as it can from the given pointer. Of course, the second parameter must be bigger than the previous malloced size, or stud will lose some memory on the end. Now this is where my problem is. When I call the line above, it doesn't change anything. The malloced array is still length of 7. I'm pretty sure, also, that I have enough memory to realloc.
Am I doing this right? Where could my problem be?
Your understanding of realloc's behaviour is nearly correct. It doesn't have to return a different pointer; it may be that there was enough unused memory after the initial block, so the heap manager can just return the same pointer back to you (but adjust its own internal state such that it knows the block is now bigger).
You have made one small mistake, though.
stud = (student*)realloc(stud, 8*sizeof(student));
Here you are replacing your stud pointer with the return value from realloc. If it happens to return NULL due to memory starvation, then you have lost your original stud pointer and the memory is leaked. You should use a temporary pointer instead.
tmp = realloc(stud, 8*sizeof(student));
if (tmp)
stud = tmp;
Also note that you still have to actually put something in the eighth slot. After the realloc the eighth slot is valid allocated memory, but contains garbage until you store something meaningful in it.
This should work, although I'd have these recommendations:
Don't cast the return from malloc. It's useless in C and may hide that you have forgotten to include <stdlib.h>.
Do not use ptr = realloc (ptr, ...) as this creates a memory leak in the case realloc returns NULL. Instead, use
if ((new_ptr = realloc (stud, 8 * sizeof (*stud))) != NULL) {
stud = new_ptr;
} else {
scream_and_die("out of memory");
}
And use sizeof (*stud), i.e. reference an expression using the pointer, not the type being pointed to (to be independent of the particular type of pointer you allocate). This way, when you rename the typedef, the malloc/realloc line needs no modification. In other words, Best Practice for Dynamic Memory Allocation in C is
#include <stdlib.h>
sometype *ptr;
...
ptr = malloc (N * sizeof *ptr);
for an array of N sometypes.

does free() follow pointers?

I'm sure it doesn't, but maybe there's black magic in it, so here's my question:
If I have a struct like this:
struct mystr {
char * strp,
unsigned int foo,
};
and I allocate memory for it and want to release it later. Do I have to do
free(mystr_var->strp);
free(mystr_var);
or is the last line enought, does the free() function follow the pointers and free them two?
No, free doesn't follow pointers, you need both lines.
I usually write a function like:
void freemystr(mystr *mystr_var)
{
if (mystr_var)
{
free(mystr_var->strp);
mystr_var->strp = NULL;
free(mystr_var);
}
}
Every individually allocated block of memory must be freed individually. free() will only free the memory block that the pointer points to and its has no knowledge of what is the content of that memory.
Hence, in your case you are doing it the right way by first freeing the innermost memory allocated in a structure and finally freeing the struct pointer.
If you just do free on the struct pointer, the struct memory gets freed. The memory held by char* strp, becomes a memory leak in your program lifetime.
No, it doesn't.
It's not magic at all, to the compiler it's just another function call.
Ask youself how you would implement void free(void *); in a way that follows pointers, of course without being fooled by being given a binary data block containing anything. You can't.
No. It simply frees the block pointed to.
You need to explictly free referenced memory. You need to do this first (i.e. most likely in the opposite direction to how you allocated the memory)
No. free won't do recursive free for all members. You have to explicitly free all members for which you have allocated memory.
If you understand how memory is allocated for struct and how free works this won't be a problem.
struct mystr {
char * strp,
unsigned int foo,
};
when you allocated memory using malloc & friends, it only allocates memory for the members.
In your case one char* and one unsigned int. Note that it doesn't allocate any memory for storing data in the char*. So you have to allocate memory for strp again before storing data. Except when you directly assign string literals Or just use the pointer strp to point to an existing memory.
Example:
case 1:
struct mystr s;
s.strp = "literals"; // valid, no need to malloc
case 2:
char *p="abc";
s.strp = p; // valid, no need to malloc
On all other usages, you must allocate memory for strp before storing data into strp.
So when you call free on the struct variable, it only frees the pointer allocated for strp and not the memory which is pointed to by strp.
It's simply because free has no information about where strp points to.
Note that in the above two examples, you don't free strp as you didn't allocate any memory there for storing data into strp. Simple rule is one free for one malloc/calloc/realloc.
C99 says,
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Resources