This question already has answers here:
How much memory would be freed if pointer is changed in C?
(3 answers)
Closed 7 years ago.
i have one scenario like below
#include <stdio.h>
int main(void) {
int *p1=NULL;
int a;
p1=&a;
printf("%p\n",p1);
p1=NULL;
printf("%p\n",p1);
return 0;
}
In this case i have no problem at all.but if i use like this as below:
#include <stdio.h>
int main(void) {
int *p1=NULL;
int a;
p1=&a;
printf("%p\n",p1);
free(p1);
printf("%p\n",p1);
return 0;
}
In this case, i got run time error as below:
Runtime error time: 0 memory: 2052 signal:11
I want to know why it is happens like that. As far i know, freeing the
pointer will do same thing as assigning it NULL value(mean when we do
free(p) it also delete the pointer link to memory instead of deleting the
allocated memory space). I would rather if you could possibly suggest me
anything on that.
Thanks in Advance.
You are trying to free() memory you haven't allocated at all, which results in Undefined Behavior.
Therefore, you need a malloc() before the free() call like
p1 = malloc(sizeof(int));
free(p1); with a p1 value not returned by malloc() produces undefined behaviour.
You have undefined behaviour:
You can only free what you've malloced. p1 points to stack allocated memory so don't attempt to free it.
Be careful too when using *p1: it has the same rules as accessing a. You need to initialise a (either with a = ... or via the pointer with *p1 = ...) before doing anything else with it. Otherwise the program behaviour is undefined.
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:
Why do these pointers cause a crash?
(5 answers)
Closed 4 years ago.
int main()
{
struct stuff
{
int num;
}*foo;
// If I comment the line below, I get core dump error.
// Why?
foo = (struct stuff *)malloc(sizeof(struct stuff));
(*foo).num = 7;
printf("%d\n", (*foo).num);
}
You are only allowed to dereference a valid pointer.
In your case, foo being an automatic local variable, unless initialized explicitly, contains some indeterminate value, i.e, it points to an arbitrary memory location, which is pretty much invalid from the point of your program.
In case, you do not assign a valid pointer to foo (returned by malloc(), for example), foo points to some indeterminate memory location and attempt to dereference it will invoke undefined behaviour.
Segmentation fault is one of the side effects of UB.
foo is a pointer, it must point to address
If you dont want to use malloc you can do follow it:
struct stuff _foo;
foo = &_foo;
(*foo).num = 7;
foo in your example is an uninitialized pointer to a struct you just defined. If you doesn't initialize with a valid memory chunk it will always result in SEGFAULT. Another bad thing with your code is that even if you allocate memory for it, than you don't free it.
If you don't want to use malloc just make it local variable:
int main()
{
struct stuff
{
int num;
}foo;
foo.num = 7;
printf("%d\n", foo.num);
}
The following application works with both the commented out malloced int and when just using an int pointer to point to the local int 'a.' My question is if this is safe to do without malloc because I would think that int 'a' goes out of scope when function 'doit' returns, leaving int *p pointing at nothing. Is the program not seg faulting due to its simplicity or is this perfectly ok?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct ht {
void *data;
} ht_t;
ht_t * the_t;
void doit(int v)
{
int a = v;
//int *p = (int *) malloc (sizeof(int));
//*p = a;
int *p = &a;
the_t->data = (void *)p;
}
int main (int argc, char *argv[])
{
the_t = (ht_t *) malloc (sizeof(ht_t));
doit(8);
printf("%d\n", *(int*)the_t->data);
doit(4);
printf("%d\n", *(int*)the_t->data);
}
Yes, dereferencing a pointer to a local stack variable after the function is no longer in scope is undefined behavior. You just happen to be unlucky enough that the memory hasn't been overwritten, released back to the OS or turned into a function pointer to a demons-in-nose factory before you try to access it again.
Not every UB (undefined behaviour) results in a segfault.
Normally, the stack's memory won't be released back to the OS (but it might!) so that accessing that memory works. But at the next (bigger) function call, the memory where the pointer points to might be overwritten, so your data you felt like bing safe there is lost.
malloc() inside a function call will work because it stores on heap.
The pointer remains until you free the memory.
And yes, not every undefined behaviour will result in segmentation fault.
It does not matter that p does not point at anything on return from doit.
Because, you know, p isn't there any more either.
It does matter that you are reading the pointer to a no-longer-existing object in main though. That's UB, but harmless on most modern platforms.
Even worse though, you are reading the non-existent object it once pointed to, which is straight Undefined Behavior.
Still, nobody is obliged to catch you:
Can a local variable's memory be accessed outside its scope?
As an aside, Don't cast the result of malloc (and friends).
Also, be aware that not free-ing memory is not harmless on all platforms: Can I avoid releasing allocated memory in C with modern OSes?
Yes, the malloc is needed, otherwise the pointer would point on the 4-byte space of the stack, which would be used by other data, if you called other functions or created now local variables.
You can see that if you call that function afterwards with a value of 10:
void use_memory(int i)
{
int f[128]={};
if(i>0)
{
use_memory(i-1);
}
}
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...
Consider the following code (building with g++):
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int a;
int b;
char c;
} memstr_t;
memstr_t *ptt_backup;
void mmm(memstr_t*& ptt)
{
ptt = (memstr_t *)calloc(15, sizeof(memstr_t));
ptt[0].a = 1;
ptt[0].b = 2;
ptt[0].c = 'c';
ptt_backup = ptt;
}
void fff()
{
free(ptt_backup);
}
int main(int argc, char *argv[])
{
memstr_t *ptt;
mmm(ptt);
printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c);
getchar();
//fff();
free(ptt); // same as fff()?
printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c); //why works?
getchar();
return 0;
}
I don't understand:
1) Why I'm not getting segfault on the second print since I free the memory? I'm still getting the values which I assigned in mmm()
2) Are free() and fff() doing the same thing?
1) Dereferencing free'd memory can do anything. It may be there, it may not, it is undefined behaviour and could do anything, including faxing your cat.
2) Yes, free() and fff() are doing the same thing as they both point to the same memory location.
Second print uses pointer that is no longer valid, that makes behavior undefined. Whatever can happen, including what makes you believe it "works", and any other time it could be something completely else. DON'T DO THAT!
2: in this code fragment they have the same effect.
calloc allocates memory and returns a pointer to the allocated memory.
In mmm you assign ptt to ptt_backup. Now both of them point to the same place. (Just because I have a name and a nickname , that doesn't make two copies of me. I am a single person accessible via two different names)
In fff you are freeing ptt_backup (read that as freeing the memory pointed by ptt_backup) which is also the one pointed by ptt.It means the memory is not available for you to use now. It can still retain values but its undefined to rely on it. See this nice answer,
Can a local variable's memory be accessed outside its scope?
printf("%d %d %c\n", ptt[0].a, ptt[0].b, ptt[0].c); may not always work.
Then when you do free(ptt) (read that as freeing the memory pointed by ptt) which is already deleted by fff, it is undefined behaviour as stated,
The free() function shall cause the space pointed to by ptr to be
deallocated; that is, made available for further allocation. If ptr is
a null pointer, no action shall occur. Otherwise, if the argument does
not match a pointer earlier returned by the calloc(), malloc(), [ADV]
posix_memalign(), realloc(), or [XSI] strdup() function, or if
the space has been deallocated by a call to free() or realloc(), the
behavior is undefined.
Using a memory pointer that points to freed memory leads to undefined behavior. This means that a segfault doesn't necessarily happen, but is possible. Therefore, you never should dereference freed memory.
They (fff and free) are the same thing in this context, because they point to the same address.
You never allocate memory for ptt_backup! You're in undefined behaviour land; anything could happen in fff()