Let's say I have this struct
typedef struct person{
char firstName[100], surName[51]
} PERSON;
and I am allocating space by malloc and filling it with some values
PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
strcpy(testPerson->firstName, "Jack");
strcpy(testPerson->surName, "Daniels");
What is the correct and safe way to free all memory taken by that struct? Is "free(testPerson);" enough or do I need to free each struct's attribute one by one?
It leads me to another question - how are structures stored in memory? I noticed a strange behaviour - when I try to print structure address it's equal to it's first attribute's address.
printf("Structure address %d == firstName address %d", testPerson, testPerson->firstName);
Which means that this
free(testPerson)
should be equal to this
free(testPerson->firstName);
and that's not what I want to do.
Thanks
Simple answer : free(testPerson) is enough .
Remember you can use free() only when you have allocated memory using malloc, calloc or realloc.
In your case you have only malloced memory for testPerson so freeing that is sufficient.
If you have used char * firstname , *last surName then in that case to store name you must have allocated the memory and that's why you had to free each member individually.
Here is also a point it should be in the reverse order; that means, the memory allocated for elements is done later so free() it first then free the pointer to object.
Freeing each element you can see the demo shown below:
typedef struct Person
{
char * firstname , *last surName;
}Person;
Person *ptrobj =malloc(sizeof(Person)); // memory allocation for struct
ptrobj->firstname = malloc(n); // memory allocation for firstname
ptrobj->surName = malloc(m); // memory allocation for surName
.
. // do whatever you want
free(ptrobj->surName);
free(ptrobj->firstname);
free(ptrobj);
The reason behind this is, if you free the ptrobj first, then there will be memory leaked which is the memory allocated by firstname and suName pointers.
First you should know, how much memory is allocated when you define and allocate memory in below case.
typedef struct person{
char firstName[100], surName[51]
} PERSON;
PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
1) The sizeof(PERSON) now returns 151 bytes (Doesn't include padding)
2) The memory of 151 bytes is allocated in heap.
3) To free, call free(testPerson).
but If you declare your structure as
typedef struct person{
char *firstName, *surName;
} PERSON;
PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
then
1) The sizeof(PERSON) now returns 8 bytes (Doesn't include padding)
2) Need to allocate memory for firstName and surName by calling malloc() or calloc(). like
testPerson->firstName = (char *)malloc(100);
3) To free, first free the members in the struct than free the struct. i.e,
free(testPerson->firstName);
free(testPerson->surName);
free(testPerson);
free is not enough, free just marks the memory as unused, the struct data will be there until overwriting. For safety, set the pointer to NULL after free.
Ex:
if (testPerson) {
free(testPerson);
testPerson = NULL;
}
struct is similar like an array, it is a block of memory. You can access to struct member via its offset. The first struct's member is placed at offset 0 so the address of first struct's member is same as the address of struct.
Because you defined the struct as consisting of char arrays, the two strings are the structure and freeing the struct is sufficient, nor is there a way to free the struct but keep the arrays. For that case you would want to do something like struct { char *firstName, *lastName; }, but then you need to allocate memory for the names separately and handle the question of when to free that memory.
Aside: Is there a reason you want to keep the names after the struct has been freed?
This way you only need to free the structure because the fields are arrays with static sizes which will be allocated as part of the structure. This is also the reason that the addresses you see match: the array is the first thing in that structure. If you declared the fields as char * you would have to manually malloc and free them as well.
Mallocs and frees need to be paired up.
malloc grabbed a chunk of memory big enough for Person.
When you free you tell malloc the piece of memory starting "here" is no longer needed, it knows how much it allocated and frees it.
Whether you call
free(testPerson)
or
free(testPerson->firstName)
all that free() actually receives is an address, the same address, it can't tell which you called. Your code is much clearer if you use free(testPerson) though - it clearly matches up the with malloc.
You can't free types that aren't dynamically allocated. Although arrays are syntactically similar (int* x = malloc(sizeof(int) * 4) can be used in the same way that int x[4] is), calling free(firstName) would likely cause an error for the latter.
For example, take this code:
int x;
free(&x);
free() is a function which takes in a pointer. &x is a pointer. This code may compile, even though it simply won't work.
If we pretend that all memory is allocated in the same way, x is "allocated" at the definition, "freed" at the second line, and then "freed" again after the end of the scope. You can't free the same resource twice; it'll give you an error.
This isn't even mentioning the fact that for certain reasons, you may be unable to free the memory at x without closing the program.
tl;dr: Just free the struct and you'll be fine. Don't call free on arrays; only call it on dynamically allocated memory.
Related
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.
I am new to C, and I am facing this problem when practicing.
The struct:
typedef struct {
char name[20];
int score[3];
int no;
} Student;
The initialize:
Student *pStudent;
strcpy(pStudent->name,"Kven");
pStudent->score[0]=1;
pStudent->score[1]=2;
pStudent->score[2]=3;
pStudent->no=1;
If the "pStudent" is not a pointer I can get it right. But if it is a pointer, I will always get a "bad access" error. How to solve it if I must use a pointer? Thank you.
A variable of type pointer stores the address in memory of another variable (it points to another variable).
Your variable pStudent is not initialized. It doesn't point to anything. In fact, it contains some garbage value that, most of the times, is the address of a memory area where the program is not allowed to write. This is why when you attempt to write there (the call to strcpy()) the operating system slaps your program over its "hand" and terminates it with the error message you mentioned.
How to correctly use pointers
One usage of pointers is to point to a certain variable that is statically allocated (defined in the program):
Student s, *pStudent = &s;
This example declares the variable s of type Student and the variable pStudent that points to it. Notice it is initialized with &s which is the address of s. Now, your code uses pStudent to initialize the fields of s.
Another usage of pointers is to dynamically allocate memory during runtime:
Student *pStudent;
pStudent = malloc(sizeof(Student));
In this situation, pStudent is initialized with the address of a new variable of type Student that is created during runtime (it doesn't have a name) by calling malloc(). malloc() allocates a block of memory (of the specified size) and return its address.
When you don't need it, you have to free the memory allocated by malloc() (using free()) for reuse:
free(pStudent);
After this call, the value of the variable pStudent doesn't change, it still points to the same address but it is invalid and using it produces undefined behaviour. You have to put the address of another Student structure in pStudent (using one of the two ways presented here) before using it again.
Student *pStudent;
should be
Student *pStudent = malloc(sizeof(Student));
Allocate memory for the pointer before writing data once done using it
free(pStudent);
Student *pStudent;
creates a pointer of type Student*. This pointer is not initialized and points to some "random" location. Allocate memory for it using malloc(or calloc) from stdlib.h:
pStudent = malloc(sizeof(Student));
and then free it after its use using:
free(pStudent);
You don't allocate any memory, you just allocate a pointer. You'll need to study pointers and how they work.
Fix the code like this:
Student student;
strcpy(student.name,"Kven");
student.score[0]=1;
student.score[1]=2;
student.score[2]=3;
student.no=1;
Alternatively you could allocate memory dynamically. But it doesn't make any sense in this case (and yet I bet at least 3 people will post answers telling you to do that...). Plus you really need to study pointers before doing dynamic allocation.
Student *pStudent = calloc(1, sizeof(Student);
if(pStudent == NULL)
{
// error handling
}
strcpy(pStudent->name,"Kven");
pStudent->score[0]=1;
pStudent->score[1]=2;
pStudent->score[2]=3;
pStudent->no=1;
...
free(pStudent);
You need to allocate memory for your structure first.
You can allocate memory with:
Student *pStudent = malloc(sizeof(Student));
And then you must release it at the end with
free(pStudent);
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.
I have a structure as below
typedef struct Mystruct{
char *name;
int telno;
struct Mystruct *nextp;
}data;
Now I malloc the structure
data *addnode;
addnode = malloc (sizeof(data));
Now I would add data to the char *name.
addnode->name = malloc (sizeof(MAX));
Question:Why is it required to malloc again?
I was under the assumption that malloc-ing the addnode will even allocate the memory for addnode->name but it is not so.
malloc is not deep and doesn't do recursion. So it won't allocate memory for any of the pointers inside the structure you pass.
If you think about this a bit more, you can see that must be so. You don't pass in any information about the structure you are allocating. You just pass a size for the memory block. Now, malloc doesn't even know what type of data you are allocating. It doesn't know that the block itself contains a pointer.
As for why this design choice was made, how can the library tell who owns the memory that your pointer refers to? Perhaps it's owned by that structure. Or perhaps you want to use that pointer to refer to some memory allocated elsewhere. Only you can know that which is why the responsibility falls to you. In fact your structure is a fine example of this. Probably the name member is owned by the structure, and the nextp member is not.
Allocating memory for Mystruct provides enough memory for a pointer to name. At this point we have no idea how many characters will be in a name so can't possibly allocate the memory for it.
If you want to fully allocate the structure in a single allocation, you could decide on a max size for name and change the structure definition to
#define MAX_NAME (10) /* change this as required */
typedef struct Mystruct{
char name[MAX_NAME];
int telno;
struct Mystruct *nextp;
}data;
Or, if you know the name when you allocate the struct, you could hide the need for two allocations from the caller by providing a constructor function
struct Mystruct* Mystruct_create(const char* name)
{
Mystruct* ms = malloc(sizeof(*ms));
ms->name = strdup(name);
return ms;
}
No. first malloc() allocates memory to whole structure including memory for holding pointer to name. i.e 4 bytes in 32 bit OS.
You need to allocate memory separately for holding data in it. by default that pointer will be pointing to some garbage location, if not initialized.
same case for free() too. i.e you have to free the inner blocks first, then free the memory for whole structure. There is no recursion kind of things in malloc() and free().
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.