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

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..

Related

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

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.

Freeing dynamically allocated int that needs to be returned but cannot be freed in main in c

As my long title says: I am trying to return a pointer in c that has been dynamically allocated, I know, I have to free it, but I do not know how to myself, my search has showed that it can only be freed in main, but I cannot leave it up to the user to free the int.
My code looks like this right now,
int *toInt(BigInt *p)
{
int *integer = NULL;
integer = calloc(1, sizeof(int));
// do some stuff here to make integer become an int from a passed
// struct array of integers
return integer;
}
I've tried just making a temp variable and seeing the integer to that then freeing integer and returning the temp, but that hasn't worked. There must be a way to do this without freeing in main?
Program design-wise, you should always let the "module" (translation unit) that did the allocation be responsible for freeing the memory. Expecting some other module or the caller to free() memory is indeed bad design.
Unfortunately C does not have constructors/destructors (nor "RAII"), so this has to be handled with a separate function call. Conceptually you should design the program like this:
#include "my_type.h"
int main()
{
my_type* mt = my_type_alloc();
...
my_type_free(mt);
}
As for your specific case, there is no need for dynamic allocation. Simply leave allocation to the caller instead, and use a dedicated error type for reporting errors:
err_t toInt (const BigInt* p, int* integer)
{
if(bad_things())
return ERROR;
*integer = p->stuff();
return OK;
}
Where err_t is some custom error-handling type (likely enum).
Your particular code gains nothing useful from dynamic allocation, as #unwind already observed. You can save yourself considerable trouble by just avoiding it.
In a more general sense, you should imagine that with each block of allocated memory is associated an implicit obligation to free. There is no physical or electronic representation of that obligation, but you can imagine it as a virtual chit associated at any given time with at most one copy of the pointer to the space during the lifetime of the allocation. You can transfer the obligation between copies of the pointer value at will. If the pointer value with the obligation is ever lost through going out of scope or being modified then you have a leak, at least in principle; if you free the space via a copy of the pointer that does not at that time hold the obligation to free, then you have a (possibly virtual) double free.
I know I have to free it, but I do not know how to myself
A function that allocates memory and returns a copy of the pointer to it without making any other copies, such as your example, should be assumed to associate the obligation to free with the returned pointer value. It cannot free the allocated space itself, because that space must remain allocated after the function returns (else the returned pointer is worse than useless). If the obligation to free were not transferred to the returned pointer then a (virtual) memory leak would occur when the function's local variables go out of scope at its end, leaving no extant copy of the pointer having obligation to free.
I cannot leave it up to the user to free the int.
If you mean you cannot leave it up to the caller, then you are mistaken. Of course you can leave it up to the caller. If in fact the function allocates space and returns a pointer to it as you describe, then it must transfer the obligation to free to the caller along with the returned copy of the pointer to the allocated space. That's exactly what the calloc() function does in the first place. Other functions do similar, such as POSIX's strdup().
Because there is no physical or electronic representation of obligation to free, it is essential that your functions document any such obligations placed on the caller.
Just stop treating it as a pointer, there's no need for a single int.
Return it directly, and there will be no memory management issues since it's automatically allocated:
int toInt(const BigInt *p)
{
int x;
x = do some stuff;
return x;
}
The caller can just do
const int my_x = toInt(myBigInt);
and my_x will be automatically cleaned away when it does out of scope.

Correct usage of free() function in C

I am new in C programming language so can you tell me if this is correct way to do.
for example:
program points on buffer and i use that pointer as parameter in free() function. So, what problems can this function cause ?
You should call free only on pointers which have been assigned memory returned by malloc, calloc, or realloc.
char* ptr = malloc(10);
// use memory pointed by ptr
// e.g., strcpy(ptr,"hello");
free(ptr); // free memory pointed by ptr when you don't need it anymore
Things to keep in mind:
Never free memory twice. This can happen for example if you call free on ptr twice and value of ptr wasn't changed since first call to free. Or you have two (or more) different pointers pointing to same memory: if you call free on one, you are not allowed to call free on other pointers now too.
When you free a pointer you are not even allowed to read its value; e.g., if (ptr) not allowed after freeing unless you initialize ptr to a new value
You should not dereference freed pointer
Passing null pointer to free is fine, no operation is performed.
Think that the computer has a whole bunch of memory not (yet) used by your program. Now you need some more memory and you ask your computer to give you some more (for example, a large buffer). Once you are done with it, you want to return it to the computer.
This memory is called the heap. You ask for memory by calling malloc() and you return it by calling free();
char *buffer;
buffer = malloc(512); // ask for 512 bytes of memory
if (buffer==NULL) return -1; // if no more memory available
...
free(buffer); // return the memory again
free() function is used to deallocate memory used by one program and move it back to available memory area so that other operating system processes can use that memory location. Also free function takes any type of pointer that points to that memory location.
For example:
int a = 10; // suppose 2 byte is allocated ie location 1000 and 1001
Now this 2 byte of memory belongs to specific problem; hence OS will not give this memory location to another process (memory is now allocated memory not available memory)
int *ptr =&a;
/*ptr is pointer variable pointing to 1000
as it is int pointer therefore ptr++ will move pointer to 1002*/
Now if we do free(ptr), it will check the pointer type and depending on type free function deallocate memory in this case 2 bytes starting from 1000.
Now interesting point is your data will be there until OS allocates this memory to some other process and that process overwrites it.
Also ptr is pointing to 1000 even after free() function but that memory location does not belong to our program hence ptr pointer has given new name DANGLING POINTER.
*ptr may or may not give the same value therefore it is better to make ptr =null.
From the man page of free() function:
The free() function frees the memory space pointed to by a pointer ptr which must have been returned by a pre‐
vious call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called
before, undefined behavior occurs. If ptr is NULL, no operation is performed.
You have to use the free() function when you are allocating the memory dynamically.
If you are using that as a static variable then it may lead to unintended behavior.
char *c=malloc(100);//allocating the 100 bytes of memory for a pointer variable c.
Here after usage of that varaible you can free that allocated memory,
free(c);
If you are declared a variable like this,
char c= malloc(100);// It is illegeal. And c will have a memory in stack.
If you free this variable,
free(c);//it will lead to system crash. Because your freeing the memory which is in stack memory.

De-allocating structures in c?

I have many structures, one of which looks like
typedef int Info;
typedef struct
{
Info info;
} Item;
So if I allocate like so:
ItemRef a;
a= malloc(sizeof(ItemRef));
where ItemRef is just typecasted int.
My question is if I deallocate a now, will info inside it also be deallocated?
Because when I tried assigning vale to info in a and then deallocating is and then printing it I was still able to access the value.
So does that mean deallocating a structure does NOT deallocate its components ? Even though I didn't have to individually allocate the components?
Deallocating a struct does deallocate the space for its members. However the rules of the C language do not require that the freed memory is zeroed out or made inaccessible in any way. All freeing does is tell the memory manager that you've finished with that bit of memory and it can reuse it at its discretion.
So, in a typical implementation, if you still have a pointer to the freed memory the compiler won't do anything to stop you accessing it. Doing so puts you in the realm of undefined behaviour which means anything can happen. Messing up in this way and accessing freed memory is a source of annoying and difficult to find bugs in C programs because the behaviour is often not consistent.
From http://opengroup.org/onlinepubs/007908775/xsh/free.html
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(), realloc()
or valloc() function, or if the space is deallocated by a call to
free() or realloc(), the behaviour is undefined. Any use of a pointer
that refers to freed space causes undefined behaviour.
As per the documentation, the free doesn't initializes all the memory bits, it freed, to any value. Thus the memory (might) still contain the old value. but its undefined behavior to refer it as stated.
The best practice is to::
free(a) ;
a = NULL ;

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