free() Function use in C? - c

I am Confused and thinking about Free Pointer in Following way , can someone clarify
I always thought that the free function just removes the address stored in the pointer, hence breaking the connection between the pointer and the space allocated for block. At the end making the values at the space a garbage value and hence making it virtually free to use by another program.
Please specify the reason why I am wrong.
Also, What happens when you point two pointers to a single space allocated
and Try to free them both? Does it Gives a compilation Error / Run Time Error?

free(ptr) de-allocates the memory block pointed to by its argument ptr, that is it returns the block to the free pool. Consecutive calls to malloc() may use that memory, re-allocating it for another purpose.
However, free() receives its argument as a copy, that is it gets the value from the ptr variable, not the variable itself. As a result it can't 'clear the pointer'. If you expect the ptr variable becomes NULL, you're wrong. That's a common mistake. You should assign ptr = NULL yourself after free() to make sure the variable value becomes unusable.
As for the memory block itself: free() is not obliged to 'make it garbage' or clear it. You can try accessing the freed memory by the same pointer, and often you will see the previous content still present there.
But don't rely on it! The memory can be reallocated for another purpose almost any time (the freed memory might even become unavailable for the process), so fiddling with it may invoke unpredictable results (so-called Undefined Behavior).
An attempt to deallocate a block twice (i.e. a second free() with the same pointer) is UB, too.

Related

Calling free on a pointer twice

I have been taught in lectures, that calling free() on a pointer twice is really, really bad. I know that it is good practice, to set a pointer to NULL, right after having freed it.
However, I still have never heard any explanation as to why that is. From what I understand, the way malloc() works, it should technically keep track of the pointers it has allocated and given you to use. So why does it not know, whether a pointer it receives through free() has been freed yet or not?
I would love to understand, what happens internally, when you call free() on a location that has previously already been freed.
When you use malloc you are telling the PC that you want to reserve some memory location on the heap just for you. The computer gives back a pointer to the first byte of the addressed space.
When you use free you are actually telling the computer that you don't need that space anymore, so it marks that space as available for other data.
The pointer still points to that memory address. At this point that same space in the heap can be returned by another malloc call. When you invoke free a second time, you are not freeing the previous data, but the new data, and this may not be good for your program ;)
To answer your first question,
So why does it not know, whether a pointer it receives through free() has been freed yet or not?
because, the specification for malloc() in C standard does not mandate this. When you call malloc() or family of functions, what it does is to return you a pointer and internally it stores the size of the memory location allocated in that pointer. That is the reason free() does not need a size to clean up the memory.
Also, once free()-d, what happens with the actually allocated memory is still implelentation dependent. Calling free() is just a marker to point out that the allocated memory is no longer in use by the process and can be reclaimed and e re-allocated, if needed. So, keeping track of the allocated pointer is very needless at that point. It will be an unnecessary burden on the OS to keep all the backtracks.
For debugging purpose, however, some library implementations can do this job for you, like DUMA or dmalloc and last but not the least, memcheck tool from Valgrind.
Now, technically, the C standard does not specify any behaviour if you call free() on an already free-ed pointer. It is undefined behavior.
C11, chapter ยง7.22.3.3, free() function
[...] 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.
C standard only says that calling free twice on a pointer returned by malloc and its family function invoke undefined behavior. There is no further explanation why it is so.
But, why it is bad is explained here:
Freeing The Same Chunk Twice
To understand what this kind of error might cause, we should remember how the memory manager normally works. Often, it stores the size of the allocated chunk right before the chunk itself in memory. If we freed the memory, this memory chunk might have been allocated again by another malloc() request, and thus this double-free will actually free the wrong memory chunk - causing us to have a dangling pointer somewhere else in our application. Such bugs tend to show themselves much later than the place in the code where they occured. Sometimes we don't see them at all, but they still lurk around, waiting for an opportunity to rear their ugly heads.
Another problem that might occure, is that this double-free will be done after the freed chunk was merged together with neighbouring free chunks to form a larger free chunk, and then the larger chunk was re-allocated. In such a case, when we try to free() our chunk for the 2nd time, we'll actually free only part of the memory chunk that the application is currently using. This will cause even more unexpected problems.
When you are calling malloc you are getting a pointer. The runtime library needs to keep track of the malloced memory. Typically malloc does not store the memory management structures separated from the malloc ed memory but in one place. So a malloc for x bytes in fact takes x+n bytes, where one possible layout is that the first n bytes are containing a linked list struct with pointers to the next (and maybe previous) allocated memory block.
When you free a pointer then the function free could walk through it's internal memory management structures and check if the pointer you pass in is a valid pointer that was malloced. Only then it could access the hidden parts of the memory block. But doing this check would be very time consuming, especially if you allocate a lot. So free simply assumes that you pass in a valid pointer. That means it directly access the hidden parts of the memory block and assumes that the linked list pointers there are valid.
If you free a block twice then you might have the problem that someone did a new malloc, got the memory you just freed, overwrites it and the second free reads invalid pointers from it.
Setting a freed pointer to NULL is good practice because it helps debugging. If you access freed memory your program might crash, but it might also just read suspicious values and maybe crash later. Finding the root cause then might be hard. If you set freed pointers to NULL your program will immediately crash when you try to access the memory. That helps massively during debugging.

What Happens If You Set Allocated Memory To NULL in C

Is there a difference between setting a pointer to NULL before and after allocating it?
For example, is there any difference between
char* c = NULL;
and
char* c = malloc(sizeof(char));
c = NULL;
What are the, if any, implications of each of those statements, and is there any difference in calling free(c) in each of those situations?
Let's look at the two cases.
Case 1: Before malloc
Well, there's almost no harm done here. Unless the pointer was pointing to something before, the pointer is simply set to NULL and points to nothing. Calling free() on a pointer that points to nothing does nothing. "Free the people?" Okay. "Free the free?" You can't really free something that's already sort of "free." No stranger, no danger. Moving on...
Case 2: After malloc
Let's break it down:
char* c = malloc(sizeof(char));
c = NULL;
The first command will reserve memory from the operating system for your program. That's dynamic allocation--getting more memory on the fly.
The second command sets your pointer to NULL. What does that mean?
Memory leak. That means your program has basically borrowed memory from the operating system and forgot about it. This is a big no-no. If a program keeps doing it over and over, they will eventually crash (or the entire system will crash).
Just like how you should always return things to friends, you should always return memory to the operating system. Therefore, you must always call free() for every point you malloc(); just like opening and closing brackets (), [], or {} in C or C++.
Never set a pointer to NULL until after you free() the memory associated with it.
Before allocating it, it might have (depending on where it was declared) garbage data in it. By assigning it to null before, you basically assure it is in a known good state.
After allocating and assigning the address to a variable, setting the pointer to null means that the pointer will no longer reference the allocated memory. Normally this creates a memory leak (a bit of allocated memory that cannot be referenced anymore, and so it cannot be freed). However there are times were this is appropriate. For example, if your logic has two references to the memory, one for allocation / deallocation purposes and one for "current item of interest" it might be appropriate to assign the current item of interest and then assign null to it as this "current item of interest" pointer is not related to memory allocation and deallocation.
Finally, if it is a pointer to be used for deallocation, after you free() the pointer, you might want to then set the pointer to null for the same reasons you set the pointer to null prior to allocation (to make sure that your program doesn't get confused by finding an address value in the pointer when that's not memory you want accessed).
Yes there's a difference. The second one causes a memory leak.
As to your second question, if c = NULL, then free(c) will have no effect.
You're not setting the allocated memory to NULL, you're setting the pointer to NULL so that it no longer points to the memory that you allocated. When you call free on it, you're not freeing the memory that you allocated, since the pointer doesn't point to it.
This is called a memory leak: you've allocated some memory, but you no longer have a pointer to it so you can't free it, so the memory will remain "in use" and unavailable to other programs even though you're not actually using it anymore.
Calling free on a NULL pointer has no effect.

Free function in c

I have allocated memory to some data type and assigned some value. Now using free is the data in the memory deleted or not? What is use of using free if the data assigned is not deleted? Can anyone help me out? Ex:
int *arr;
arr=(int*)malloc(sizeof(int)*1000);
assert(arr!=NULL);
/*Some operation*/
arr[123]=354;
//some operations
printf("%d",*(arr+123));
//calling some funcs
free(arr);
printf("\n%d",*(arr+123));
The point of free is to make the memory you allocated available for following calls to malloc. It does not guarantee that the buffer passed to it is wiped in any way.
In fact, what you're doing is provoking undefined behavior; accessing a buffer that has been free'd might give the value that was previously stored in it, or any other value, or it might crash your program, or do anything else.
You cannot "delete" things from memory.
What free() does is it reclaims the memory, so that it can be recycled by a future call to malloc().
You cannot legally dereference a pointer that you got from malloc() (or any other dynamic allocation call) after calling free() on it. Doing so invokes undefined behavior.
By using malloc you set aside a specified number of bytes to be used for what ever you want. Returned is an address to the area. The memory area is also flagged in a special table as occupied meaning it can't be reserved by another process or another malloc.
When you free the allocated memory the area is flagged as free, but the data is not erased. If you want to erase the data you'll have to do a memset or manually loop and set data to 0 or some other value before you free it.
As mentioned by others the operation on free memory is undefined.
A short introduction to how memory can be arranged. Look i.e. at heap:
http://www.geeksforgeeks.org/archives/14268 or Fig 1. at bottom of this comment: Strange global variable behaviour, once variable name is changed issue disappears
I have written some more about the malloc process itself here:
Can some explain the performance behavior of the following memory allocating C program? where also virtual vs. physical memory, pages etc are some of the points.

Why are the contents pointed to by a pointer not changed when memory is deallocated using free()?

I am a newbie when it comes to dynamic memory allocation. When we free the memory using void free(void *ptr) the memory is deallocated but the contents of the pointer are not deleted. Why is that? Is there any difference in more recent C compilers?
Computers don't "delete" memory as such, they just stop using all references to that memory cell and forget that anything of value is stored there. For example:
int* func (void)
{
int x = 5;
return &x;
}
printf("%d", *func()); // undefined behavior
Once the function has finished, the program stops reserving the memory location where x is stored, any other part of the program (or perhaps another program) is free to use it. So the above code could print 5, or it could print garbage, or it could even crash the program: referencing the contents of a memory cell that has ceased to be valid is undefined behavior.
Dynamic memory is no exception to this and works in the same manner. Once you have called free(), the contents of that part of the memory can be used by anyone.
Also, see this question.
The thing is that accessing memory after it has been freed is undefined behavior. It's not only that the memory contents are undefined, accessing them could lead to anything. At least some compilers when you build a debug version of the code, actually do change the contents of the memory to aid in debugging, but in release versions it's generally unnecessary to do that, so the memory is just left as is, but anyway, that is not something you can safely rely upon, don't access freed memory, it's unsafe!
In C, parameters are passed by value. So free just can't change the value of ptr.
Any change it would make would only change the value within the free function, and won't affect the caller's variable.
Also, changing it won't be so much help. There can be multiple pointers pointing to the same piece of memory, and they should all be reset when freeing. The language can't keep track of them all, so it leaves the programmer to handle the pointers.
This is very normal, because clearing the memory location after free is an overhead and generally not necessary. If you have security concerns, you can wrap the free call within a function which clears the region before freeing. You'll also notice that this requires the knowledge of the allocation size, which is another overhead.
Actually the C programming language specifies that after the lifetime of the object, even the value of any pointer pointing to it becomes indeterminate, i.e. you can't even depend on the pointer to even retain the original value.
That is because a good compiler will try to aggressively store all the variables into the CPU registers instead of memory. So after it sees that the program flow calls a function named free with the argument ptr, it can mark the register of the ptr free for other use, until it has been assigned to again, for example ptr = malloc(42);.
In between these two it could be seen changing the value, or comparing inequal against its original value, or other similar behaviour. Here's an example of what might happen.

how 'free' works when pointer is incremented

When malloc is called, the size is stored adjacent to the allocated block so that free will know how much to free etc ( http://c-faq.com/malloc/freesize.html ).
My question is, Say we have dynamically allocated memory and later in the code we increment the pointer
pointer++
And then later, if i call a
free(pointer)
what memory does actually get freed up.
Is it number of allocated bytes starting from the current address pointed by 'pointer' or from the base address to which it has been allocated.
You need to free() the same pointer as you received from malloc(). Incrementing, altering or changing it is undefined behaviour, that is usually a segmentation fault.
Think of the pointer you receive as a book from a library. You get home and read it. Afterwards you remove the front page and the book's back and hand it back to the librarian. Will he accept it or are you in serious trouble now? ;-)
You can only call free() on a value that you previously obtained from malloc(), calloc(), or realloc() (or NULL). Everything else is undefined.
For example, an implementation might store the size of the allocated block in 4 bytes before the return address from malloc(). Then, free() goes back 4 bytes and finds out the size. This wouldn't work if you don't pass the original pointer back to free().
It will cause undefined behavior. Most likely it will crash your program either instantly or later.
That's undefined behavior. And it will most probably results in problem later on.
If you increment the pointer without saving the original malloced location you can't call free on it. You have to save the original location somewhere and use a temporary point when you increment.
doing pointer++ to original pointer is terribly wrong. result of freeing it may be different on different implementations, but you definitely shouldn't do it.
The code managing the free storage just assumes that you wouldn't hand it the wrong pointer. It takes whatever you give, doesn't check its plausibility, and interprets it the same way it would interpret the right pointer. It will act according to whatever values it reads from whatever memory locations it looks at assuming the pointer was rightfully obtained. If you handed it a stray pointer, it will find nonsensical values and thus act nonsensical.
This is called undefined behavior and it's a mean thing. It might format your hard drive, toast your CPU, or make your program seemingly work the way it is expected to until you retire. You never know.
This is what we call a memory leak/segmentation fault.
You HAVE to pass the same pointervalue to free() as the one you got from malloc() or your application will misbehave/crash.
The pointer returned by malloc() points directly to the memory on the heap that will be used by your program.
However, this isn't the only memory that's allocated. A few bytes are allocated in the memory locations immediately preceding the pointer returned that indicate the size of the chunk on the heap. This isn't used by your program, but it will definitely be needed by free.
When free(p) is called, the information about its chunk on the heap is contained in, say, the locations from p-4 through p-1. This depends on implementation of course, but the details need not concern the programmer. The only thing that the programmer needs to know is that free uses that area of memory to free the chunk of memory from the heap, and that area is derived from the original pointer p.
In other words, if you call free on p, it will only make sense if malloc once returned exactly p.
If you pass in a pointer that wasn't created with malloc, who knows what will lie at p-1, p-2, etc.? It will probably result in a catastrophic failure.

Resources