What happens to the data that is present in a memory location that has just been freed by a free() ? Is that data also deleted and the memory will now have a garbage value ? Or that data still persists there untill a new data is stored in that memory location (in future) ?
I mean, for code below:
int *ptr;
ptr = malloc(sizeof(int));
*ptr = 1;
// Suppose ptr = 2000
//Free now
free(ptr);
// My question is what is the value stored in memory address 2000 now ?
// Is it still '1' or some garbage value ?
The result is unpredictable. There are several options that can happen. The point is that you cannot rely on any behavior of the memory released by free()
Some examples:
the memory can be untouched (remain the same as it is with the same data).
It can be given to another memory allocation, in which case it can be written over at any point.
It can be zeroed.
The page containing the memory can be returned to the OS, removing it from the memory map of your process, making your program crash if you try to access it.
Whether or not the value is overwritten is undefined. Once free is called it is allowed to leave the memory as-is or it can overwrite it, but if you are interested in security you should overwrite it yourself before deallocating it. Speaking of deallocation, free doesn't have to give the memory back to the operating system, and in fact in many cases it won't, instead it will keep the memory allocated to your program so that the next time you call malloc it can simply give you back the same memory and avoid having to make more system calls, since the time it takes for memory allocation from the operating system is generally considered a less efficient use of resources than the program keeping a bit more memory allocated than it needs.
I know that using the C free() function the memory used is released, but neither the pointer, nor the value contained in the memory is modified! free() only tells that the memory may be used for other purposes. (It may be some libraries implementations clean the freed memory or the pointer value, but this should not be the standard!)
I tried the code below with gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
int main(void)
{
int *i,j;
i=malloc(100*sizeof(int));
for(j=0;j<100;j++)
i[j]=j+1;
printf("%p %d\n",i,i[0]);
free(i);
printf("%p %d\n",i,i[0]);
return 0;
}
The output results (as I expected) is:
0x1de2010 1
0x1de2010 1
Malloc() is a library function. The answer depends upon how the library is implemented.
Most (if not all) mallocs prefix a header to the memory block returned. This is usually modified.
Some mallocs append a trailer to the memory block and write something to it. This is used to detect buffer overruns.
Some frees() will overwrite the write the returned memory with some bit pattern to detect subsequent writes.
There are a lot of mallocs out there that you can download and link with your application so you can get nearly any behavior you want by linking the malloc you want with your application.
It depends on the compiler. If you are using gcc then after free value of that memory is become 0.
Here is a sample code:
#include<stdio.h>
#include<stdlib.h>
int main ( void )
{
int *ptr = NULL;
ptr = malloc (sizeof(int));
*ptr = 5;
printf ( "\n value of *ptr = %d", *ptr );
free ( ptr );
printf ( "\n value of *ptr = %d", *ptr );
return ( 0 );
}
o/p:
./a.out
value of *ptr = 5
value of *ptr = 0
./a.out
value of *ptr = 5
value of *ptr = 0
./a.out
value of *ptr = 5
value of *ptr = 0
Dereferencing a freed pointer leads to undefined behavior, which means anything is allowed to happen.
Most likely, you'll get some garbage value, but you might also trigger a segmentation fault, which will crash your program. Even so, neither of those behaviors are guaranteed, and you shouldn't rely on them.
Related
The code is as follow :
#include <stdlib.h>
int num = 3; // Static external variable
int *ptr = #
int main(void)
{
int num2 = 4; // Automatic variable
int *ptr2 = &num2;
free(ptr); //Free static variable
free(ptr2); //Free automatic variable
return 0;
}
I try to compile the above code and it works, I'm curious does the free() function able to free both the static variable and also automatic variable? Or basically it does nothing?
Calling free() on a pointer not returned by memory allocating functions(malloc,calloc etc) causes Undefined Behavior.
Your code has an Undefined Behavior, So the compiler does not need to give you any diagnostic of it and it can show any behavior, it might work, or crash, or literally do anything.
Just avoid writing code which causes an Undefined Behavior is the only solution.
You shouldn't do that. free is only used for memory dynamically allocated from heap by malloc family of functions.
Memory for num is statically allocated in data segment and can't be released. Memory for num2 is allocated in the main's call stack frame and will be released as soon as main returns.
What actually happens depend on implementation of free. There are usually specific data structures maintained in heap to help malloc/free track the allocated and free memory areas. free expects these data structures to be somewhere around the place its argument points to. An when you pass it a pointer which doesn't point to a malloc-allocated heap area, it'll consider garbage data as some useful information and do some strange things. And you're lucky if the result is just an immediate program crash.
This question already has answers here:
C - Accessing data AFTER memory has been free()ed?
(2 answers)
Closed 2 years ago.
I am new to C. I have below codes. After free, the first freed pointer give 0 length but not null, the second and third still have length > 0. Not sure if it is normal? Thanks.
Here is the output:
enter image description here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *str[3];
char *aa = "helloworld0";
char *bb = "helloworld1";
char *cc = "helloworld2";
str[0] = (char *)malloc(strlen(aa) + 1);
strcpy(str[0], aa);
str[1] = (char *)malloc(strlen(bb) + 1);
strcpy(str[1], bb);
str[2] = (char *)malloc(strlen(cc) + 1);
strcpy(str[2], cc);
char **strr = str;
printf("Before free----Length:%ld,Content:%s,Address:%p\n",
strlen(strr[1]), strr[1], strr[1]);
free(strr[1]);
if (strr[1]) printf("not NULL 1\n");
printf("After free----Length:%ld,Content:%s,Address:%p\n\n",
strlen(strr[1]), strr[1], strr[1]);
printf("Before free----Length:%ld,Content:%s,Address:%p\n",
strlen(strr[0]), strr[0], strr[0]);
free(strr[0]);
if (strr[0] == NULL) printf("not NULL 0\n");
printf("After free----Length:%ld,Content:%s,Address:%p\n\n",
strlen(strr[0]), strr[0], strr[0]);
printf("Before free----Length:%ld,Content:%s,Address:%p\n",
strlen(strr[2]), strr[2], strr[2]);
free(strr[2]);
if (strr[2]) printf("not NULL 2\n");
printf("After free----Length:%ld,Content:%s,Address:%p\n\n",
strlen(strr[2]), strr[2], strr[2]);
}
After passing a pointer value to free, any further use of that value has undefined behavior. Even if (strr[1]) is invalid and does not have a meaningful result, even if in practice it normally reflects that the last time the value was meaningful, it was non-null.
The subsequent operation is even worse:
printf("After free----Length:%ld,Content:%s,Address:%p\n\n",strlen(strr[1]),strr[1],strr[1]);
Here you're not only using the value strr[1] (a pointer), but passing a function that will use it to access an object at that address (strlen). This also has undefined behavior, and mechanically it ends up accessing memory that no longer belongs to your program. What this results in is a matter of how the compiler implementation handles undefined behavior it can see (note: it could even trap before letting you get this far, but it doesn't have to) and possibly on what the C library implementation (free) does with memory you've relinquished to it. It's possible that the address will no longer work and that accesses to it will fault and cause your program to crash. It's also possible that it ends up accessing memory that now belongs to the implementation, possibly with new contents stored there to track it for reuse. It's also possible that entirely different and unexpected results are produced.
In C you simply can't do this. After you free memory obtained by malloc, you're done with it. You can't process the pointer or the memory it pointed to before in any way. There is no way to "check if it was freed". Once it's freed, that's it.
Many programmers like to assign a null pointer value to any pointer object as soon as they free the memory it points to, to prevent inadvertently trying to access it later:
strr[1] = NULL; // or = 0;
Free memory actually means freeing ownership of specified place in the memory. The idea is that in the process of freeing it the variable it self can't write anymore off the given location but only read. In order to actually make the code safe after every free you should set the variable to NULL. It will redirect the variable off the last memory's sell it was pointing to and make the data unreadable from the variable it self. Instead the pointer will hold a NULL which is pre known state of a pointer free of ownership and thus may be used.
free means you are telling system:
I do not need this memory anymore, you can use this memory anytime if you want.
But system does not guarantee when will it clean and re-use these memory.
Next time when you access this memory, maybe system has not cleaned it yet, or maybe it does. You just can not make sure whether it does. It is a undefined behavior.
You should add strr[1]=NULL; to prevent you accidentally access the space which you have already returned to system.
In the below program, as far as in my knowledge once we allocate some memory then if we are chaging the address from
ptr to ptr++, then when we are calling free with ptr i.e free(ptr).
Then the program should crash.
But in this program works fine.
How it works?
I am using Code::Bocks in Windows XP.
Please help me.
int main()
{
int *ptr;
ptr = malloc(1);
*ptr = 6;
printf("The value at *ptr = %d \n", *ptr);
ptr++; //Now ptr is address has been changed
free(ptr); // Program should crash here
ptr = NULL;
/* *ptr = 5;*/ // This statement is crashing
return 0;
}
The behavior of this program is undefined from the very moment that you store a value through an int* pointing to a single byte. There's no guarantee of a crash.
Specifically, it seems like your free doesn't (maybe can't) check its argument properly. Try running this program with a malloc debugging library.
Absence of a crash does not necessarily mean your code is fine. On another platform, it will probably crash.
BTW: you should rather malloc(sizeof(int))
The program should not necessarily crash, the behavior is undefined.
It works only due to luck; the code is still wrong.
To understand why, one first needs to be familiar with the implementation of the malloc library itself. malloc not only allocates the space it returned for you to use, it also allocates space for its own metadata that it uses to manage the heap (what we call the region of memory managed by malloc). By changing ptr and passing the wrong value to free, the metadata is no longer where free expected it, so the data it's using now is essentially garbage and the heap is corrupted.
This doesn't necessarily mean it'll crash due to say, a segfault, because it doesn't necessarily dereference a bad pointer. The bug still exists and will likely manifest itself in a longer program with more heap usage.
In the following code segment, after free(x), why does y become 0?
As per my understanding, the memory in the heap that was being pointed to by x, and is still being pointed to by y, hasn't been allocated to someone else, so how can it change to 0?
And moreover, I don't think it is free(x) that changed it to 0.
Any comments?
#include <stdio.h>
int main(int argc, char *argv[])
{
int *y = NULL;
int *x = NULL;
x = malloc(4);
*x = 5;
y = x;
printf("[%d]\n", *y); //prints 5
free(x);
printf("[%d]\n", *y); //why doesn't print 5?, prints 0 instead
return 0;
}
This is undefined behavior, explanations are just speculation.
I can speculate that maybe you are running a debug version of the C library, and that the debug version of free() does zero the pointed area.
What is done in free depends on the implementation. It is not prohibited to zero out the memory after it's freed.
And what you're doing is undefined behavior.
Doesn't y points to the same address as x, after line
y = x;
If you free x, you will also free the memory pointed by y.
If you are wondering why it prints '0', that undefined behavior, but I've seen it as a practice before, that some programmers, sets the freed area to '0'.
Download this video called "Binky the pointer fun video" (it's not a joke, actually is very educative), and you'll get pointers better.
The call to free() will put the memory block that had been allocated by malloc() back onto data structures that the C runtime maintains for the heap (in this case something that might be called the 'free-list).
Manipulating the heap data structures might incidentally change what was being pointed to by y (since the program doesn't own the memory anymore, it has no reason to believe the memory shouldn't change).
In a non-debug build of the program, the runtime typically won't do anything specifically to invalidate freed memory, but as I mentioned, it may still make changes as a result of its own bookkeeping (though since the memory doesn't belong to the caller anymore, the runtime is allowed to do whatever it likes).
In a debug build, the runtime will probably explicitly overwrite the memory to a value that is likely to be invalid if the program does use it in the hopes that it will cause a problem that identifies the problem more readily. Usually the value used to overwrite the freed memory block isn't zero, since zero will often not expose a bug (i.e. NULL pointer checks will cause the code to 'handle' the invalid memory access). For example, MSVC's debug heap manager will overwrite freed memory with the value 0xDD (see When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete? for more details).
I've a question about the memory management in C (and GCC 4.3.3 under Debian GNU/Linux).
According to the C Programming Language Book by K&R, (chap. 7.8.5), when I free a pointer and then dereference it, is an error. But I've some doubts since I've noted that sometimes, as in the source I've pasted below, the compiler (?) seems to work according a well-defined principle.
I've a trivial program like this, that shows how to return an array dynamically allocated:
#include <stdio.h>
#include <stdlib.h>
int * ret_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i*2;
}
printf("Address pointer in ret_array: %p\n", (void *) arr);
return arr;
}
int * ret_oth_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i+n;
}
printf("Address pointer in ret_oth_array: %p\n", (void *) arr);
return arr;
}
int main(void)
{
int *p = NULL;
int *x = NULL;
p = ret_array(5);
x = ret_oth_array(6);
printf("Address contained in p: %p\nValue of *p: %d\n", (void *) p, *p);
free(x);
free(p);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
If I try to compile it with some arguments: -ansi -Wall -pedantic-errors, it doesn't raises errors or warning. Not only; it also runs fine.
Address pointer in ret_array: 0x8269008
Address pointer in ret_oth_array: 0x8269038
Address contained in p: 0x8269008
Value of *p: 0
Memory freed.
*p+4 = 8
*x = 0
*(p+4) is 8 and *x is 0.
Why does this happen?
If *(p+4) is 8, shouldn't *x be 6, since the first element of the x-array is 6?
Another strange thing happens if I try to change the order of the calls to free.
E.g.:
int main(int argc, char * argv[])
{
/* ... code ... */
free(p);
free(x);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
In fact in this case the output (on my machine) will be:
*p+4 = 8
*x = 142106624
Why does the x pointer is really "freed", while the p pointer is freed (I hope) "differently"?
Ok, I know that after freeing memory I should make the pointers to point to NULL, but I was just curious :P
It is undefined behaviour, so it is an error to deference freed pointer as strange things may (and will) happen.
free() doesn't change the value of the pointer so it keeps pointing to the heap in the process address space - that's why you don't get segfault, however it is not specified and in theory on some platforms you can get segfault when you try to dereference pointer immediately after freeing.
To prevent this it is a good habit to assign pointer to NULL after freeing so it will fail in predictable way - segfault.
Please note that on some OSes (HP-UX, may be some others as well) it is allowed to dereference NULL pointer, just to prevent segfault (and thus hiding problems). I find it rather stupid as it makes things much more difficult to diagnose, although I don't know the full story behind this.
free() (and malloc()) are not from gcc. They come from the C library, which on Debian is usually glibc. So, what you are seeing is glibc's behavior, not gcc's (and would change with a different C library, or a different version of the C library).
I particular, after you use free() you are releasing the memory block malloc() gave you. It's not yours anymore. Since it is not supposed to be used anymore, the memory manager within glibc is free to do whatever it wants with the memory block, including using parts of it as its own memory structures (which is probably why you are seeing its contents change; they have been overwritten with bookkeeping information, probaly pointers to other blocks or counters of some sort).
There are other things that can happen; in particular, if the size of your allocation was large enough, glibc can ask the kernel for a separate memory block for it (with mmap() or similar calls), and release it back to the kernel during the free(). In that case, your program would crash. This can in theory also happen in some circunstances even with small allocations (glibc can grow/shrink the heap).
This is probably not the answer you are looking for, but I'll give it a try anyway:
Since you're playing with undefined behaviour that you should never depend on in any way, shape or form, what good does it do to know how exactly one given implementation handles that?
Since gcc is free to change that handling at any given time, between versions, architectures or depending on the position and brightness of the moon, there's no use whatsoever in knowing how it handles it right now. At least not to the developer that uses gcc.
*(p+4) is 8 and *x is 0. Why does this happen? If *(p+4) is 8, shouldn't *x be 6, since the first element of the x-array is 6?
One possible explanation for this would be that printf("...%i..."...) might internally use malloc to allocate a temporary buffer for it's string interpolation. That would overwrite the contents of both arrays after the first output.
Generally, I would consider it an error if a program relies on the value of a pointer after it has been freed. I would even say that it's a very bad code smell if it keeps the value of a pointer after it has been freed (instead of letting it go out of scope or overwriting it with NULL). Even if it works under very special circumstances (single-threaded code with a specific heap manager).
Once you free the dynamic-memory variable, it is not yours. The memory manager is free to do what ever it sees better with that piece of memory you where pointing to. The compiler doesn't do anything as far as I know with the freed blocks of memory, because it is a function and not defined by the language. Even if it is defined by the languages, the compiler just inserts calls to the underlying OS functions.
Just wanna say, It is undefined by the language, So you have to check your OS and watch that piece of memory after freeing it. The behavior maybe random, because sometimes other programs ask for memory, sometimes not!
by the way, It is different on my machine, the value changes for both pointers.
Although the behavior you're seeing seems to be consistent, it is not guaranteed to be so. Unforeseen circumstances may causes this behavior to change (let alone the fact that this is completely implemetnatation dependent).
Specifically, in your example you free() the array and then get the old content when you access the array. If you'll have additional malloc() calls after the free() - chances are that the old contents will be lost.
Even if the memory is freed, it is not necessarily reused for some other purpose. Old pointers to your process memory are still valid pointers (though to unallocated memory) so you do not get segmentation faults either.