This question already has answers here:
Why freed struct in C still has data?
(7 answers)
Closed 8 years ago.
int main(int argc, char **argv)
{
counter = 0;
int size = 5;
struct trie *mainTrie = malloc(size * sizeof(mainTrie));
test(mainTrie);
printf("%c", mainTrie[2].alphabet);
free(mainTrie->alphabet);
printf("%c", mainTrie[2].alphabet);
return 0;
}
The test functions was just to see how I can use malloc. My experiment was successful except one thing: free(mainTrie).
When I added printf("%c", mainTrie[2].alphabet) after I 'freed' the memory spaces, the output still gave me the same letter that was stored at mainTrie[2].alphabet from method 'test'.
Am I not understanding something? Thanks in advance...
Show us your complete code, specially the maintree struct. It seems like you need to free the maintree variable:
free(maintree);
However, freeing memory means that the piece of memory you reserved will be available to the O.S again. It doesn't mean you actually set that piece of memory tu NULL. Edit: #MattMcNabb "Typically the memory is not released to the OS, just made available for further allocations from the same process. (This depends on a lot of things of course)"
It is possible that you are printing a piece of memory that doesn't belong to your program anymore, but the data hasn't changed yet.
Note these 2 important things from the documentation
A block of memory previously allocated by a call to malloc, calloc or realloc is deallocated, making it available again for further allocations. (just deallocated, doesn't say anything about the values being changed)
If ptr does not point to a block of memory allocated with the above functions, it causes undefined behavior.
If ptr is a null pointer, the function does nothing.
Notice that this function does not change the value of ptr itself, hence it still points to the same (now invalid) location. (so you maybe pointing to a piece of memory you allocated in the past, but it still has the same values, it is possible, it wont happen all the time).
Related
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.
This question already has answers here:
What REALLY happens when you don't free after malloc before program termination?
(20 answers)
Closed 3 years ago.
If I use malloc() to allocate memory and do not use free() to de-allocate the
the memory. why cannot that memory be accessed by other program by just over writing the previous content
void main()
{
int *a; //here a is holding a junk value
MALLOC(a,1,int);
*a=100; //a is holding 100
MALLOC(a,1,int);
*a=200; //a is holding 200
/* so memory location where the value 100 is stored is inaccessible
cannot be reused */
//why can't we just over write that memory space when used next time
}
You are using a very strange macro, the allocations in standard C would read:
int * const a = malloc(sizeof *a);
if (a != NULL)
{
*a = 100;
}
then the second allocation is done without calling free(), and overwriting the contents of a; this is very bad since it leaks the memory. That's why I declared it as * const above, to signal that the pointer variable in typical use should not be overwritten since we want to keep its value.
When your program ends, on typical modern systems, all resources used by that process will be reclaimed by the operating system and the memory will be used for something else.
The need to call free() is mostly about allocations done while your program runs, if the allocations happen repeatedly the process will just grow and grow otherwise.
This question already has answers here:
How do malloc() and free() work?
(13 answers)
Closed 8 years ago.
I am new at programming and i just don't get this. I am supposed to make a function which takes an 1d Array as argument, and frees this Array.
I've got this:
void destroy(double A[])
{
free(A);
}
and my main:
void main()
{
swrmeg = (double *)malloc ((10)*sizeof(double));
swrmeg[0] = 3,2;
destroy(swrmeg);
printf("%lf\n",swrmeg[0]);
}
This is supposed to give a segmentation fault, but it does not, it prints the first double of the array. This means the array has not been freed.. Any ideas why does this happen?
Any proper ways to do the freeing in a function?
You're freeing it correctly.
Doing something wrong, like accessing a piece of memory after it's been freed, doesn't necessarily mean you'll get a segmentation fault, any more than driving on the wrong side of the road means you'll necessarily have an accident.
Segfaults cannot be guaranteed when doing undefined operations, they just sometimes occur when doing undefined operations.
What is actually occurring in your case is that the memory has been assigned to your program in the malloc and then your program has decided it doesn't need it in the free statement; however, the operating system has decided not to move it's memory fences in such a manner to cause a segfault.
Why it doesn't do so includes a lot of reasons:
It could be far more expensive to move the fence rather than just to let your program get away with having a few extra bytes for a little while.
It could be that you'll ask for some memory in a few minutes, and if you do (and it's small enough) then the same memory will be returned, without the need to move memory fences.
It could be that until you hit some hardware dependent limit (like a full page of memory) the OS can't reset the memory fence.
It could be ...
That's the reason why it is undefined, because it is basically dependent on so many things that all the implementations do not need to align. It is the defined part that needs to align.
It appears you are being asked to investigate undefined behavior (UB). ( This is supposed to give a segmentation fault ) What you are doing is not guaranteed to get a seg fault, but you can increase your chances by writing to places you do not own:
void main()
{
swrmeg = (double *)malloc ((10)*sizeof(double));
swrmeg[0] = 3,2;
destroy(swrmeg);
printf("%lf\n",swrmeg[0]);
}
void destroy(double *A)
{
int i;
for(i=0;i<3000;i++)//choose a looping index that will have higher likelyhood of encroaching on illegal memory
{
A[i] = i*2.0; //make assignments to places you have not allocated memory for
}
free(A);
}
Regarding using free'd memory: This post is an excellent description of why free'd memory will sometimes work. (albeit, dealing directly with stack as opposed to heap memory, concepts discussed still illustrative on using free'd memory in general)
Program was programmed in C and compiled with GCC.
I was trying to help a friend who was trying to use trying to (shallow) copy a value that was passed into a function. His the value was a struct that held primitives and pointers (no arrays or buffers). Unsure of how malloc works, he used it similar to how the following was done:
void some_function(int rand_params, SOME_STRUCT_TYPEDEF *ptr){
SOME_STRUCT_TYPEDEF *cpy;
cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));// this line makes a difference?!?!?
cpy = ptr;// overwrites cpy anyway, right?
//prints a value in the struct documented to be a char*,
//sorry couldn't find the documentation right now
}
I told him that the malloc shouldn't affect the program, so told him to comment it out. To my surprise, the malloc caused a different output (with some intended strings) from the implementation with the malloc commented out (prints our garbage values). The pointer that's passed into the this function is from some other library function which I don't have documentation for at the moment. The best I can assume it that the pointer was for a value that was actually a buffer (that was on the stack). But I still don't see how the malloc can cause such a difference. Could someone explain how that malloc may cause a difference?
I would say that the evident lack of understanding of pointers is responsible for ptr actually pointing to memory that has not been correctly allocated (if at all), and you are experiencing undefined behaviour. The issue is elsewhere in the program, prior to the call to some_function.
As an aside, the correct way to allocate and copy the data is this:
SOME_STRUCT_TYPEDEF *cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));
if (cpy) {
*cpy = *ptr;
// Don't forget to clean up later
free(cpy);
}
However, unless the structure is giant, it's a bit silly to do it on the heap when you can do it on the stack like this:
SOME_STRUCT_TYPEDEF cpy = *ptr;
I can't see why there difference in the print.
can you show the print code?
anyway the malloc causes memory leak. you're not supposed to allocate memory for 'cpy' because pointer assignment is not shallow-copy, you simply make 'cpy' point to same memory 'ptr' point by storing the address of the start of that memory in 'cpy' (cpy is mostly a 32/64 bit value that store address, in case of malloc, it will store the address of the memory section you allocated)
This question already has answers here:
Why do I get different results when I dereference a pointer after freeing it?
(7 answers)
Closed 9 years ago.
Below is the code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p;
p=(int *)malloc(sizeof(int));
*p=5;
printf("Before freeing=%p\n",p);
printf("Value of p=%d\n",*p);
//making it dangling pointer
free(p);
printf("After freeing =%p\n",p);
printf("Value of p=%d\n",*p);
return 0;
}
Below is the output:
Before freeing=0x1485010
Value of p=5
After freeing =0x1485010
Value of p=0
After freeing the pointer, dereferencing gives the output "0"(zero).
Below is another code that also gives '0'
include <stdio.h>
#include <stdlib.h>
int main()
{
int *p;
p=(int *)malloc(sizeof(int));
printf("Before freeing=%p\n",(void *)p);
printf("Value of p=%d\n",*p);
return 0;
}
In this i have not freed the memory , just allocated it , still it gives '0' .
Is it like the default value of every uninitialized pointer is '0'??
why is it so ?
Don't rely on this, it's undefined behaviour. free() doesn't have to set the pointer to zero, this is just what your current implementation is doing for you. If you want to be 100% sure, regardless of your compiler, platform, etc. set your pointer to NULL after freeing it.
This is simply undefined behavior if we look at the C99 draft standard Annex J.2 which covers undefined behavior says:
The behavior is undefined in the following circumstances:
and included the following bullet:
The value of a pointer that refers to space deallocated by a call to the free or
realloc function is used (7.20.3).
Setting a pointer to NULL after free'ing is usually a good idea and you can find a good discussion here on that topic.
Dereferencing an invalid pointer leads to undefined results per spec. It's not guaranteed to fail.
While the answers "it doesn't matter, it is UB" are in general sufficient, one might be curious why the value changes. Curiosity is (IMHO) a valid reason to know the reason of why something happens.
It depends on the memory management which might decide to store addresses of the "next free block" or whatever in a freed memory area.
So what you observe is probably an action of the memory management.
For example, the memory management MIGHT be implemented in that way that it manages two linked lists and an upper pointer. One linked list contains the allocated memory chunks, pointing maybe 8 or 16 bytes before the "really usable" memory, and the other linked list points to the first free chunk, which in turn contains a pointer to the next one. The memory above the upper pointer is considered as free.
If you free the first memory block, the free list pointer points to it, and its first pointer sized data is zeroed, meaning that there is no other freed block. And there is your reason why the memory is zeroed out.
It is nice to know that things like these exist and how they work, but refrain the temptation to make use of that knowledge in production programs. One day they may fall onto your feet...