How should I free all memory created using multiple realloc? - c

I created array with 10 integer size using malloc. I added values to the elements. Then, I reallocated it to 200 bytes into newArr. And then I reallocated newArr into newArr2 with size of 10 integers again. Code:
void main(){
int i, *arr = (int *)malloc(10* sizeof(int));
for(i=0; i<10; i++){
arr[i] = i;
}
int *newArr = (int *)realloc(arr, 200);
int *newArr2 = (int *)realloc(newArr, 10* sizeof(int));
}
How should I use free to remove all the allocated memory here? I'm getting error while clearing all of them.
Edit: As per the accepted answer the old memory should've been cleared but it didn't. I was able to access memory and was able to change value on old address.

From my point of view, when you use malloc or realloc you're changing the memory reference, so, if you call realloc on a variable you are freeing the old space used and allocate new space, copying the old data to the new memory position, so, in your example, arr doesn't hold a valid memory address after first realloc. The same thing happen on newArr

realloc is basically malloc with the new size, memmove the data to the new block and free the old one. (But implementation can optimize this process because they've got more information they can use, like just extending the current allocated block, producing the same pointer)
So the pointers arr and newArr are invalid and shouldn't be accessed anymore because they might have been freed, so the pointer in newArr2 is the current one and valid, if the previous allocations didn't fail. So free(newArr2) is the correct answer.
Sure, you might access the memory from the old pointers, but it isn't guaranteed because it might've been allocated and overwritten for a different purpose or you might just be lucky to get the same pointer back from realloc (because from eg. the optimization above). It's just undefined behavior when accessing freed memory.
Source on reddit

Related

Malloc doesn't doesn't add new memory

I'm having trouble when I try to use malloc to allocate new space for floats inside my array.
My goal is to dynamically create array, and malloc to add a space for new float each time I want to add a new float.
Here is the code I am trying to run, but each time it only allocates an array with sizeof(float), even though the variables keep increasing.
float *funkcia_e(FILE **subor, int *pocet_cien) {
float *pole_cien;
*pocet_cien = 1;
while (fgets(nazov, sizeof nazov, *subor) != NULL)
{
pole_cien = (float*) malloc((*pocet_cien) * 4);
fscanf(*subor, "%f", &pole_cien[pozicia++]); //This causes problems
*pocet_cien = *pocet_cien + 1;
}
}
int main() {
int pocet_cien = 1;
float *pole_cien = NULL;
funkcia_r(&subor, pole_cien, &pocet_cien);
}
Here is the recorded debugging: https://s.put.re/RR6wqRk.mp4
It appears the malloc actually corrupts the array, instead of exntending it. Any ideas?
You need to use realloc. It does what you wanted malloc to do, i.e. lets you extend a previously allocated block. In contrast, malloc is a one-shot deal: you get your memory block, and that's what you have to work with.
(from the comment) cant afford to realloc, as I have to allocate the array dynamically and realloc would purge the contents of array when reallocating it.
That is not true: when realloc extends the amount of memory allocated to your program, and decides that it must re-allocate the block, it copies the content of the current block into the new block, up to the allocated size of the old block, so the new block is ready to use. Hence, your current program results in a memory leak.
In order to let main use results of allocation you must pass the pointer pole_cien by pointer, i.e. as float**. Otherwise the results of assigning it inside funkcia_e are not propagated to main.
A few other points to consider:
Do not cast malloc results
Do not hard-code size of float as 4; use sizeof(float)
Make sure pocet_cien starts at zero, and use it in place of pozicia; add 1 on the call to realloc.
It is quite obvious as malloc does not "add" any memory, but allocates a new chunk of it - every time fresh. So eventually you access not allocated memory and you get the memory fault as index increments all the time but you allocate the space for 4 elements.

C - memset vs free

I am confused on what actually happens in memory when memset is called versus what happens when you call free.
For example I have a pointer A that points to an array of char*'s
char** A = (char**)calloc(5, sizeof(char*));
int i;
for(i=0;i<5;i++)
{
//filling
A[i] = (char*)calloc(30, sizeof(char));
scanf("%s", &A[i]);
}
now I want to reset it my char** pointer and all the elements
it points to be completely empty
memset(A, 0, 5);
or
free(A);
what is the difference?
I am somewhat new to C so please speak in layman's terms thank you
The difference is that memset actually sets the value of a block of memory, while free returns the memory for use by the operating system.
By analogy using physical things, memset(beer, 0, 6) applied to a six-pack of beer would apply the value of '0' to all six members of the array beer, while free(beer) would be the equivalent of giving the six-pack away to a friend.
The memset function sets an area of memory to the requested value. Do note that the size you provide is the number of bytes.
The free function releases the allocated memory so it can't be used anymore. Calling free doesn't usually modify the memory in any way. Using the memory after calling free leads to undefined behavior.
Both approaches are incorrect, but somewhat complementary.
memset will set the content of the buffer to the given value, 0 in your case. This will change the value of the pointers, which will cause you to lose the references to the allocated buffers (in each A[i]).
free(A) will release the buffer pointed by A, but this buffer contains pointers, and each of the buffers that is pointed by them will not be freed.
in short - memset does not free a dynamically allocated buffer, and free does not set it to zero.
A correct approach will be something like that:
for(i=0;i<5;i++)
{
// complementary to
// A[i] = (char*)calloc(30, sizeof(char));
free(A[i]);
}
// complementary to
// char** A = (char**)calloc(5, sizeof(char*));
free(A);
A = NULL; // so no one gets confused...
free deallocates the memory, which means A would still be pointing to the same memory location, which is invalid now.
memset will set the memory currently pointed to by A, to whatever you want.
memset changes the contents at the memory address. It does not alter whether the memory is allocated/deallocated.
free does not change the contents at the memory address. It deallocates the block of memory which makes it available for the program to reclaim and reuse. Therefore any pointers to this block become invalid and trying to access the memory should result in a Segfault ("if you're lucky" as my professor would say).
Use memset when you know you are going to be accessing the data at that address again. Use free when you know that the data will no longer be accessed ever again and that the program may reclaim that memory.
memset() method just replaces the x memory bytes with a given character the allocated memory which is pointed by a pointer *a;
memset(a, 'a', x);
The prototype of memset() method is:
void* memset(void*, unsigned int, int);
memset() behaves like strcpy() but the difference is that memcpy() copied the data as it is (byte), but strcpy copies the formatted string as well (so takes more time than memcpy to execute).
However, free() method just deallocates the memory space and makes it available to get occupied.
While other answers explain the difference, let me add an example when both memset() and free() will need to be used together, in a specific order:
If the malloc'ed memory region was used to store any critical/valuable information that needs to be erased to prevent others from snooping on it (say some security-related stuff like managing a password or some other crypto), you would want to first erase the contents in that memory region and then call free() on it to give away that region's control back to the OS.
Hence, just like free() is the opposite of malloc(), memset(to zero)-then-free() is the opposite of calloc().

pointer to a pointer, which is pointing to a memory block, which pointer should be freed?

At the end of the code below, which pointer would I need to plug into free(), array or temp_array? Does it matter which one or would either free the memory block?
int *array = 0;
int *temp_array = 0;
int count = 0;
array = malloc(sizeof(int));
// skipping code where count is calculated...
temp_array = realloc(array, count * sizeof(int));
if (temp_array == NULL) {
free(array);
// some error message
return;
}
array = temp_array;
// skipping section of code, which reads numbers from a file and loads them into an array
// amount of numbers read can be 0 to whatever
free (array); // free array or temp_array?
Also, is it possible to allocate a block of memory with realloc if the pointer it's trying to allocate memory for is NULL (in other words, do I need to allocate memory first with malloc and later resize it with realloc, or can I skip the malloc)?
It doesn't matter - both temp_array and array point to the same memory block. I would prefer temp_array as then the realloc and free pointers match. Depending on your working code, for protection you could consider assigning both pointers to NULL to prevent free-ing the memory twice. free(NULL) is safe - no operation is performed.
Regarding the initial alloc of one integer - is that necessary? From the code shown, an int defined on the stack would be preferable.
EDIT:
After more info from OP (in comments) it appears the code can be simplified using an header value which holds the number of records in the file. This eliminates the need for realloc and permits memory allocation prior to reading the file values in.

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.

realloc and the ghosts of mallocs past

I know that realloc will free memory when necessary, and I know the third rule of C - "for every malloc there must be an equal and opposite free"... but how do these two work together?
The situation is best described in code:
int main()
{
myStruct **myStructArray;
int i, num_elements;
num_elements = getnumber(); // gets value for num_elements
myStructArray = (myStruct **) malloc(num_elements * sizeof(myStruct*));
for (i=0; i<num_elements; i++)
myStructArray[i] = (myStruct *) malloc(sizeof(myStruct));
// so far so good...
num_elements = getnumber(); // gets new, LOWER value
myStructArray = realloc(myStructArrary, num_elements * sizeof(myStruct*));
// rest_of_code, and necessary free loop for myStructArray etc...
}
Obviously the above is nothing more than a snippet, but a snippet paints a thousand words.
Would this create a memory leak? I know the call to realloc will free the pointers' memory, but I can see arguments for and against the possibility that there is still going to be a bunch of memory forgotten about.
A leak can be circumvented by incorporating int number_elements_new into the code and loop free-ing the surplus myStructs before calling realloc to free the (now NULL) pointers.
If realloc does the donkeywork and frees up ALL the associated memory that's great, otherwise I've got to trawl through to make sure nothing has been missed - myStruct itself contains allocated memory and so on.
Thank you for your recommendations...
malloc, realloc and free have no idea about what the memory is being used for. If you're using the memory to store pointers to other dynamically-allocated memory, then that's for you to tidy up!
Also, note that the way you're using realloc in your code snippet is potentially unsafe. If realloc fails, it leaves the original memory un-freed, and returns NULL. Best practice is to assign the return value to a temporary pointer, and then check. See e.g. http://www.c-faq.com/malloc/realloc.html.
If you're shrinking the size of your array, you would first need to free each myStructArray[i] where i >= num_elements, otherwise you will have a memory leak.
Put another way, shrinking the size of the pointer array does not affect the memory that each array element was pointing to.
Also, in the realloc call, you will want to assign the result to a temporary pointer; if realloc cannot extend or shrink the buffer, it will return NULL, and you'll lose your reference to that block, which will also introduce a leak:
myStruct **tmp = realloc(myStructArray, ...);
if (tmp)
{
myStructArray = tmp;
...
}
If the number is lower than the existing number of elements, you will introduce a memory leak as the reallocated block is not related to the content and you are losing your reference to the blocks allocated in the for-loop.
Therefore you'll have to loop through your array and free all elements that will be subject to removed.
If the number is higher than the existing number, it won't create a memory leak as realloc copies the existing data if a new memory block has been allocated. Therefore your other dynamically allocated blocks (malloc in the for loop) are still referenced by the resized array. The only gotcha here is, that the newly allocated array spaces are uninitialized and can therefore contain invalid pointers.

Resources