freed allocated memory still accessable [duplicate] - c

This question already has answers here:
Using pointer after free()
(6 answers)
C - Accessing data AFTER memory has been free()ed?
(2 answers)
Accessing a freed pointer, shouldn't output be a segmentation fault?
(2 answers)
Closed 2 years ago.
I'm freeing a variable I allocated using malloc, but after I've freed it I try to access it and it still works fine.
I would expect a segmentation fault when accessing this memory but I dont get one.
Here is a simple example to show the problem:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int*)malloc(5*sizeof(int));
arr[0] = 2;
arr[4]=9;
free(arr);
printf("%d\n",arr[4]);
return 0;
}
The output is 9.

I am sorry to say, the problem seems to be that you expect a segmentation fault.
The C language standard doesn't require a segmentation fault. Once you access a freed pointer anything can happen - including nothing.
Most likely, the memory allocator cached the memory for re-use instead of returning the memory to the system. This way, in case you would need to allocate memory again, the second allocation would be faster.
This means that, from a system's point of view, your program still "owns" that memory.
From an allocator's point of view, that memory is owned by the allocator and you shouldn't use it (the allocator might write its own data over there).
From your program's point of view you have a quite bug.

Related

Why is struct in C working even with less memory allocation? [duplicate]

This question already has answers here:
Writing to pointer out of bounds after malloc() not causing error
(7 answers)
Closed 2 years ago.
Malloc function in C allocates the size of memory passed into it's argument in bytes.
Here my struct variable has two integer values.So size of struct should be 8 bytes. I am only allocating 1 bytes and it's still working.
Why?
C (gcc)
#include <stdio.h>
#include <stdlib.h>
struct node{
int a;
int b;
}ab;
int main(){
struct node * nl=(struct node *)malloc(1); //I am allocating memory here
nl->b=89;
nl->a=45;
printf("%d %d %ld",nl->a,nl->b,sizeof(int));
}
Try it online!
When you write past the end of allocated memory, you invoke undefined behavior, which means you can't reliably predict what the program will do. It could crash, it could output strange results, or (as in this case) it can appear to work properly.
How undefined behavior manifests itself can change by making a seemingly unrelated change, such as adding an unused local variable or adding a call to printf for debugging. It could also change by compiling with different optimization settings or with a different compiler.
Just because the program could crash doesn't mean it will.
On most architectures, memory is allocated in 4k "pages" and no smaller. Malloc is placing your single requested byte somewhere in either one of these pages or just beyond the program break.
As long as you don't write beyond the allocated page, the virtual memory system is unaware of your transgression and won't segfault you. Of course, there's no way of knowing if or when an illegal access will happen, and thus in the C standard this behavior is undefined.

Why can I store a variable of to a memory location when the variable has a bigger size than the memory allocated? [duplicate]

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Is it undefined behaviour to access an array beyond its end, if that area is allocated? [duplicate]
(3 answers)
Array index out of bound behavior
(10 answers)
Getting no segmentation fault when exceeding the size that was allocated for a char * [duplicate]
(1 answer)
Closed 5 years ago.
The title may not be accurate. Please excuse me for being a completely new programmer in c. But it is a genuine question which I believe will benefit others who were as confused by memory and pointers as I was when learning my first low-level programming language, that is C.
Here is what I know in regard to this:
Pointers are variables that store memory addresses.
You can allocate a place in memory using the malloc function from the stdlib.h header file, which returns a pointer to the memory allocated.
The malloc function takes the size of what you want to store in bytes as a parameter
Which leads me to ask: What if you store something of a bigger size in the place in memory allocated by the malloc function, where you passed a smaller size as the parameter for the malloc function?
Naturally, the first thing I did was obviously try it. I take input using scanf, which then stores the input in the allocated memory. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *string_pointer;
string_pointer = malloc(sizeof(char)*24);
if (string_pointer == NULL){
puts("Memory allocation failed:(");
return 1;
}else{}
scanf("%s",string_pointer);
printf("%s",string_pointer);
return 0;
}
You can see that I allocated a place in memory, passing in sizeof(char)*24 as the parameter. Then I stored the pointer of this memory in the string_pointer variable.
Now if I feed scanf with a string that is more than 24 characters (bigger size than the allocated memory), it still works, When I print out the contents of the memory, I get the whole string as it is, even though that means that it stored a string of a bigger size than what it can hold. This shows that I have an obvious misconception of how memory allocation works. It might be because that malloc doesn't allocate a memory that can only hold the size that I passed to malloc, and the whole size parameter thing is for a totally different purpose.
I am completely confused? How come I just stored a string in a memory allocated that can hold less than the size of the string?

C - free() doesn't delete my structure malloc [duplicate]

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).

function to free memory of 1D Array [duplicate]

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)

segmentation fault while accessing memory area [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Invalid read/write sometimes creates segmentation fault and sometimes does not
I was doing some experimentation with malloc and wrote this very small program on a linux m/c:
int main(){
int *p=NULL;
p = (int *)malloc(10);
*(p + 33*1000) = 5;
free(p);
return 0;
}
This program is not giving segmentation fault but if i change the line 5 to this
*(p + 34*1000) = 5;
Then it gives a segmentation fault. On my system the page size is 4K.
I am not able to explain why its giving a segmentation fault at around 128Kb(34*1000 is around 128K) after p.
If anyone can explain this with the perspective of memory management in linux that would be great.
You are accessing beyond the memory you allocated for p with both *(p+33*1000),*(p+34*1000) which is undefined behaviour. You can't reason out as it may "work" or crash or anything can happen.
You are modifying memory that you have not allocated yourself - the address you are writing to is way beyond the limits of your array. Whenever you write beyond an array bounds you run the risk of a segfault - it depends on the memory location. It may not segfault depending on the address, but there is no way that this is a good thing to do and results will be unpredictable.
This program exhibits undefined behavior (per the C standard) and, strictly speaking, there's nothing else to explain about it.
The language standard does not in any way describe how memory management is or should be implemented at the low level on any particular platform. Some memory areas can be accessible despite you not explicitly allocating them.
After allocating space for 10 integers you can only dereference those 10 by *(p+0), *(p+1), ... ,*p(p+8) ,*p(p+9). No more else you're beyond the extents of what you've allocated.
Dereferencing elsewhere may mean you're attempting to use an invalid pointer, and hence the segmentation fault.
May be that's the available memory in the system.
In this case all <= 33 * 1000 will pass and all >= 34 *1000 will fail.

Resources