Free function in c - 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.

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.

Understanding C Memory Allocation and Deallocation

I have been recently trying to learn how to program in the C programming language.
I am currently having trouble understanding how memory is deallocated by free() in C.
What does it mean to free or release the memory?
For instance, if I have the following pointer:
int *p = malloc(sizeof(int));
When I deallocate it using free(p), what does it do? Does it somehow flag it as "deallocated", so the application may use it for new allocations?
Does it deallocates only the pointer address, or the address being pointed is also deallocated too?
I would do some experiments myself to better understand this, but I am so newbie in the subject that I don't know even how to debug a C program yet (I'm not using any IDE).
Also, what if int *p is actually a pointer to an array of int?
If I call free(p), does it deallocate the whole array or only the element it is pointing to?
I'm so eager to finally understand this, I would very much appreciate any help!
What does it mean to free or release the memory?
It means that you're done with the memory and are ready to give it back to the memory allocator.
When I deallocate it using free(p), what does it do?
The specifics are implementation dependent, but for a typical allocator it puts the block back on the free list. The allocator maintains a list of blocks that are available for use. When you ask for a chunk of memory (by calling malloc() or similar) the allocator finds an appropriate block in the list of free blocks, removes it (so it's no longer available), and gives you a pointer to the block. When you call free(), the process is reversed -- the block is put back on the free list and thereby becomes available to be allocated again.
Importantly, once you call free() on a pointer, you must not dereference that pointer again. A common source of memory-related errors is using a pointer after it has been freed. For that reason, some consider it a helpful practice to set a pointer to nil immediately after freeing it. Similarly, you should avoid calling free() on a pointer that you didn't originally get from the allocator (e.g. don't free a pointer to a local variable), and it's never a good idea to call free() twice on the same pointer.
Does it deallocates only the pointer address, or the address being pointed is also deallocated too?
When you request a block of memory from the allocator, you specify the size of the block you want. The allocator keeps track of the size of the block so that when you free the block, it knows both the starting address and the block size. When you call free(p), the block that p points to is deallocated; nothing happens to the pointer p itself.
Also, what if int *p is actually a pointer to an array of int?
An array in C is a contiguous block of memory, so a pointer to the first element of the array is also a pointer to the entire block. Freeing that block will properly deallocate the entire array.
I'm so eager to finally understand this, I would very much appreciate any help!
There are a number of good pages about memory allocation in C that you should read for a much more detailed understanding. One place you could start is with the GNU C Library manual section on memory allocation.
As alluded to above and in the other answers, the actual behavior of the allocator depends on the implementation. Your code shouldn't have any particular expectations about how memory allocation works beyond what's documented in the standard library, i.e. call malloc(), calloc(), etc. to get a block of memory, and call free() to give it back when you're done so that it can be reused.
malloc and free do whatever they want. Their expected behaviour is that malloc allocates a block of desired size in dynamic memory and returns a pointer to it. free must be able to receive one such pointer and correctly deallocate the block. How they keep track of the block size is irrelevant.
Is int *p a pointer to an array of ints ? Maybe. If you allocated sufficient space for several ints, yes.
There is a fixed and limited amount of memory in your computer, and everybody wants some. The Operating system is charged with the task of assigning ownership to pieces of memory and keeping track of it all to assure that no one messes with anyone else's.
When you ask for memory with malloc(), you're asking the system (the C runtime and the OS) to give you the address of a block of memory that is now yours. You are free to write to it and read from it at will, and the system promises that no one else will mess with it while you own it. When you de-allocate it with free(), nothing happens to the memory itself, it's just no longer yours. What happens to it is none of your business. The system may keep it around for future allocations, it may give it to some other process.
The details of how this happens vary from one system to another, but they really don't concern the programmer (unless you're the one writing the code for malloc/free). Just use the memory while it's yours, and keep your hands off while it's not.

How are we able to access the pointer after deallocating the memory?

As per my understanding,
free() is used to deallocate the memory that we allocated using malloc before.
In my following snippet, I have freed the memory i have allocated. But i was able to access the pointer even after freeing? How it is possible?
How free works internally?
#include<iostream>
using namespace std;
int main()
{
int *p=(int *)malloc(sizeof(int));
*p=17;
free(p);
*p=*p+1;
printf("\n After freeing memory :: %d ",*p );
return 0;
}
You can certainly continue to use p after calling free(p) and nothing will stop you. However the results will be completely undefined and unpredictable. It works by luck only. This is a common programming error called "use after free" which works in many programs for literally years without "problems" -- until it causes a problem.
There are tools which are quite good at finding such errors, such as Valgrind.
Accessing a dangling pointer will result in undefined behavior.
A dangling pointer is the one which is already freed.
After free(p), p is a dangling pointer which points to no where. free() just releases the memory block allocated by malloc() and it doesn't change the value of pointer pointing to heap in that process address space. On some platforms you might get segfault if you try dereferencing pointer after freeing. Its good practice if you assign pointer p to NULL after freeing.
In most systems and standard libraries, malloc is optimized by allocating a larger chunk of memory than required (up to 64K on some systems) from the OS, and then internally disbursing it as per requirement from this pool. The same applied to the deallocation (free) as well, in that, the free'd memory isn't freed, but put back in the memory pool, in case another request comes in, in which case the pool is reused.
Thus, the call to free hasn't actually freed the memory from the process's address space and is thus accessible even after free.
My understanding as to why this is done is that system calls are expensive, so the initial call to malloc will make a system call for enough memory that future requests for malloc do not immediately trigger another system call for more memory.
As for further reading, please take a look at this page on Wikipedia, How do malloc() and free() work? and How is malloc() implemented internally?

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.

free() not freeing up memory properly?

I'm trying to free up the memory I've allocated with malloc, but the free command doesn't seem to do its job properly according to Eclipse's debugger. How's this possible?
Below is a screenshot of my debugger after it supposedly freed up seCurrent->student->year, which is clearly not the case. year was allocated using malloc.
alt text http://img693.imageshack.us/img693/7840/codeo.png
free() does not normally change any values in your program - it just makes adjustments to the C runtime heap. This means that the values in the memory that was just freed are retained. However, attempts to access them from your code lead to undefined behaviour.
What makes you think it hasn't freed it? Freeing memory means that accessing it from the program thereafter is undefined behavior, and the memory is available for re-use next time you call malloc. It does not promise to overwrite the data that was stored in the memory you freed, or to prevent the debugger from reading the unallocated memory.
Free will return the allocated space to the heap to be reused by subsequent mallocs but it does not change the values of any pointers that previously referenced that memory. In your case, no other mallocs have yet been performed so the memory just freed is still the same as it was just prior to the call to free. In order for your code to know that there is no longer any data associated with the pointer, you may want to set it to null after freeing the memory associated with it.
when you malloc() some memory, all it does is searching for some free space in memory, and keeping track it is now used. It doesn't initialize it or whatever.
when you call free(), all it does is clearing this memory block out of the list of used memory blocks. Again it doesn't modify the contents.

Resources