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)
Related
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).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a;
a = (int *)malloc(100*sizeof(int));
int i=0;
for (i=0;i<100;i++)
{
a[i] = i+1;
printf("a[%d] = %d \n " , i,a[i]);
}
a = (int*)realloc(a,75*sizeof(int));
for (i=0;i<100;i++)
{
printf("a[%d] = %d \n " , i,a[i]);
}
free(a);
return 0;
}
In this program I expected the program to give me a segmentation fault because im trying to access an element of an array which is freed using realloc() . But then the output is pretty much the same except for a few final elements !
So my doubt is whether the memory is actually getting freed ? What exactly is happening ?
The way realloc works is that it guarantees that a[0]..a[74] will have the same values after the realloc as they did before it.
However, the moment you try to access a[75] after the realloc, you have undefined behaviour. This means that the program is free to behave in any way it pleases, including segfaulting, printing out the original values, printing out some random values, not printing anything at all, launching a nuclear strike, etc. There is no requirement for it to segfault.
So my doubt is whether the memory is actually getting freed?
There is absolutely no reason to think that realloc is not doing its job here.
What exactly is happening?
Most likely, the memory is getting freed by shrinking the original memory block and not wiping out the now unused final 25 array elements. As a result, the undefined behaviour manifests itself my printing out the original values. It is worth noting that even the slightest changes to the code, the compiler, the runtime library, the OS etc could make the undefined behaviour manifest itself differently.
You may get a segmentation fault, but you may not. The behaviour is undefined, which means anything can happen, but I'll attempt to explain what you might be experiencing.
There's a mapping between your virtual address space and physical pages, and that mapping is usually in pages of 4096 bytes at least (well, there's virtual memory also, but lets ignore that for the moment).
You get a segmentation fault if you attempt to address virtual address space that doesn't map to a physical page. So your call to realloc may not have resulted in a physical page being returned to the system, so it's still mapped to you program and can be used. However a following call to malloc could use that space, or it could be reclaimed by the system at any time. In the former case you'd possibly overwrite another variable, in the latter case you'll segfault.
Accessing an array beyond its bounds is undefined behaviour. You might encounter a runtime error. Or you might not. The memory manager may well have decided to re-use the original block of memory when you re-sized. But there's no guarantee of that. Undefined behaviour means that you cannot reason about or predict what will happen. There's no grounds for you to expect anything to happen.
Simply put, don't access beyond the end of the array.
Some other points:
The correct main declaration here is int main(void).
Casting the value returned by malloc is not needed and can mask errors. Don't do it.
Always store the return value of realloc into a separate variable so that you can detect NULL being returned and so avoid losing and leaking the original block.
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.
Hi I have following code
#include <stdio.h>
#include <conio.h>
typedef struct test
{
int a;
int b;
int c[10];
}tester;
typedef struct done
{
tester* t;
int nn;
}doner;
void main()
{
doner d;
d.t = (tester*)malloc(sizeof(d.t));
d.t->a = 10;
d.t->c[0] = 10;
printf("%d\n", d.t->a);
getch();
return;
}
I think the statement:
d.t = (tester*)malloc(sizeof(d.t));
is incorrect it should be:
d.t = (tester*)malloc(sizeof(tester));
but when I run this code it is not crashing please let me the why is this.
The fact that it is not crashing is because it has undefined behavior. The correct code is the second one, but no need for casting.
d.t = malloc(sizeof(tester));
Also, You need to free the malloc'ed pointer.
On many system, the heap is not checked when writing to the malloc'ed buffer, but only when freeing the allocated memory. In such case, you will probably get some kind of crash when you free the memory.
The fact that it's not crashing is a big reason why these sort of memory allocation bugs are so insidious and hard to detect. Your program only allocates the one structure, and doesn't fill it up, so the fact that it runs past the amount of memory allocated to it doesn't affect anything else.
If your program made more use of dynamically-allocated memory, then either the calls to malloc/free would trigger a crash because your structure overwrote the heap's linking metadata, or other parts of the program writing to their own malloc'ed data would overwrite your structure. Either way, not pretty.
Yes, you're right. It should be sizeof(tester), because d.t is just a pointer.
Now if you write sizeof(d.t) you invoke Undefined Behavior which is not a guarantee of crash. The program may run correctly, run incorrectly, crash, or order a pizza. There is no guarantee of what will happen with a program that has undefined behavior, even prior to the construct that leads to it.
As freeing the malloced memory - in this small sample program you don't need to worry about it, because the system will free the memory after your program exits, but in general you should try to free whatever you've allocated so as to avoid memory leaks in larger programs.
By default, the linker asks the OS to allocate 1MiB of (stack) memory for the program at the start-up. Your program doesn't crash because all of the references are still in the same memory (same address space) which was reserved by the OS for your program. Technically you haven't allocated that memory, but as the pointers are still in the valid memory range so your program can access it.
This is just like, in most cases, you can write to d.t->c[10] (although valid indexes are 0-9)
Crashes occur when pointers are used which correspond to memory locations outside the allocated memory. Google Page Fault for detailed understanding, if you are interested.
help me in understanding the malloc behaviour.. my code is as follows::
int main()
{
int *ptr=NULL;
ptr=(int *)malloc(1);
//check for malloc
*ptr=1000;
printf("address of ptr is %p and value of ptr is %d\n",ptr,*ptr);
return 0;
}
the above program works fine(runs without error)...how?? as I have supplied a value of 1000 in 1 byte only!!
Am I overwriting the next memory addresss in heap?
if yes, then why not sigsgev is there?
Many implementations of malloc will allocate at a certain "resolution" for efficiency.
That means that, even though you asked for one byte, you may well have gotten 16 or 32.
However, it's not something you can rely on since it's undefined behaviour.
Undefined behaviour means that anything can happen, including the whole thing working despite the problematic code :-)
Using a debug heap you will definitely get a crash or some other notification when you freed the memory (but you didn't call free).
Segmentation faults are for page-level access violations, and a memory page is usually on the order of 4k, so an overrun by 3 bytes isn't likely to be detected until some finer grained check detects it or some other part of your code crashes because you overwrote some memory with 'garbage'