This question already has answers here:
Should one really set pointers to `NULL` after freeing them?
(10 answers)
Closed 3 years ago.
int main(){
(int*) pointer = (int*) malloc(sizeof(int));
free(pointer);
}
I learned from 'Prata, Stephen. C Primer Plus (Developer's Library)' that
"When the function terminates, the pointer, being an automatic variable, disappears." so simply, i don't need to null the pointer
however, I also learned from school that the pointer becomes a dangling pointer if it doesn't get nulled after it free.
Two ideas are contradicting each other. Which one is the right one?
According to the docs:
The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
Therefore, you don't need to set pointer to nullptr (in C++11) or NULL (in C and before C++11) if it goes out of scope immediately after you free it because then you have no chance to dereference a dangling pointer.
However, if the pointer is still in the scope after a call to free, than the good practice would be to set it to nullptr or NULL so that the following checks would work:
C++:
if (nullptr != ptr) {...}
C:
if (NULL != ptr) {...}
C and C++:
if (!ptr) {...}
What free does is to deallocate the space that pointer holds before the execution of free. The pointer holds an integer value(the address) before and after the execution therefore the address that the pointer holds is now an invalid address that is not allocated by the program. As said, if you plan to use the pointer again in future cases, you wouldn't wanna have an invalid undefined value in it that you cannot check, having null makes the checks easier.
Related
This question already has answers here:
Is malloc() initializing allocated array to zero?
(9 answers)
Closed 4 years ago.
I am still confused with the two functions malloc() and calloc()
As we know calloc() initialize the memory it allocates while malloc() doesn't.
But when I tried the following code, the result seemed unexpected.
typedef struct{
int *val;
}Node;
int main()
{
Node *q=(Node*)malloc(sizeof(Node));
if(q->val==NULL) printf("malloc initialized memory\n");
Node *p=(Node*)calloc(1,sizeof(Node));
if(p->val==NULL) printf("calloc initialized memory\n");
}
The variables 'val' of val of p and q are both NULL. Isn't q->val uninitialized?
Can anyone explain it to me? Thanks!
The malloc function does not initialize the memory it allocates. The contents will be indeterminate (and might seem "random" or "garbage").
If you want to zero-initialize the memory (which means that all pointers are NULL) then use calloc, or explicitly initialize the data.
Also note that in C you should not cast the return of malloc (and siblings).
When a variable is uninitialized, formally it means that its value is indeterminate. It could be any value, and 0 is just as random as any other value. Just because you read 0 doesn't necessarily mean the variable was initialized.
You're actually invoking undefined behavior by attempting to read q->val because 1) it was not initialized and 2) its address was never taken. Had its address been taken first you would not have undefined behavior unless the indeterminate value was a trap representation.
The memory chunk returned via malloc(), contains indeterminate value. Attempt to use that value may incur unspecified result, as nothing about the value can be guranteed.
Quoting C11, chapter 7.22.3.4/P2
The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
This question already has answers here:
Is free() zeroing out memory?
(7 answers)
What is Undefined Behaviour in C? [duplicate]
(5 answers)
Closed 5 years ago.
I have this code:
int * m = (int *)malloc(sizeof(int));
printf("%p %i\n", m, *m);
(*m) = 6;
printf("%p %i\n", m, *m);
free(m);
printf("%p %i\n", m, *m);
I run it on Linux. Why the value of the memory address is always 0?
Why if I run it on Windows this value changes?
Let us see the C11 standard, chapter ยง7.22.3.3.
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. [....]
So, that means, the pointer which was passed to free() is no longer a "valid" pointer in your program context. Thereby, attempting to access the pointer, you're essentially accessing an invalid memory which causes undefined behavior.
Now, what actually happens to the memory location and to the content of the memory location, is depending on the memory manager or the OS. It could just be left as-is, unless it is required to be allocated again by some further calls, it could either be zeroed-out, anything...that is beyond the C standard specification.
Then, I'm not preaching for the coding style, but I personally find it handy to set any free-d pointer to NULL immediately after free(). "Most of the time", this will prevent any further use of the pointer (via a segfault), as NULL is definitely an invalid pointer in all context.
That said, some points regarding your code snippet,
Please see this discussion on why not to cast the return value of malloc() and family in C..
You must cast the argument to %p to void * as printf() is a variadic function and there's no default argument promotion applicable.
After calling free(), the pointer itself contains the old address to memory which is now possibly invalid. The pointed-at value has an indeterminate value, which could be anything. Reading it can result in a crash, a random garbage value or some manner of seemingly deterministic value - what will happen is not well-defined.
You can't know what will happen and there are no guarantees. Therefore, pondering why you get a certain value when you do this is meaningless practice, even for learning purposes. You shouldn't access that memory, simple as that.
In C, must I always initialize my last node pointing to NULL? I generally see this happening in tutorials and in books. But to my understanding, an unitialized pointer holds the same address as a NULL pointer. So why initialize?
But to my understanding, an uninitialized pointer holds the same address as a NULL pointer
It might, by (bad) luck.
In any case reading out an uninitialised pointer invokes undefined behaviour. Whether this would lead to a crash (or any other "strange" behaviour) sooner or later is unknown, as by the nature of undefined behaviour.
However depending on how the memory the pointer variable "lives" in is allocated, the memory might come as "already" initialised, if allocating
it statically or
via calling calloc()
Both methods allocate memory and 0 it out in advance. Which, for most recent systems, is sufficient to have a pointer variable (living inside this memory) carrying the value of NULL.
But please note that there still might be implementations around that use a different bit pattern for NULL than just 0-bits. So to stay 100% portable it is good advice to always initialise with NULL explicitly and not rely on implicitly cleared out memory. And btw, this also helps the potential reader of your sources.
When you create a pointer without initializing it, let's say
char *ptr;
The memory points to some bytes (depending on your pointer type).
Those bytes, may be anything. Like some previous initialized unfreed pointer, or, to some garbage.
Which is not the same as a NULL pointer.
To avoid that, you should take the habit of initializing every of your pointers (except for globals and statics which are initialized to 0) and, add a NULL every-time you work with arrays or anything containing multi-elements.
Let's say that in this case, NULL is the '\0' of the array/list.
For example, if you want to create an array containing a few char *, do it this way :
void function()
{
char *array[4];
array[0] = strdup("Jason");
array[1] = strdup("Mike");
array[2] = strdup("Nicole");
array[3] = NULL;
}
It helps you not to go further than the memory you previously allocated for this pointer, avoiding memory fails, and segmentation faults. In case you're using a counter to get through every case of this array.
Otherwise, don't use NULL everywhere, if you allocated a string, don't fill it with NULL after on.
int main()
{
char *ptr;
if ((ptr = malloc(sizeof(char) * 42)) == NULL)
return (-1);
ptr = NULL;
return (0);
}
This won't work because you're sending NULL into the bytes you cleaned straight before.
If you want to properly use a pointer and clean it before using it, you can use memset. Which will send a x amount of the same byte into the pointer, cleaning the garbage that might be in it by the bytes you passed into memset parameters.
You might think that null pointer is the pointer that is uninitialized, but it's wrong. Null pointer is a special pointer which doesn't points to anywhere.
// To declare a null pointer.
int *ptr=NULL;
if(ptr==NULL) //..do something..
Functions like malloc() and getchar() returns null pointer in case they are unable to perforn their task or complete the task.
An uninitialized pointer can hold any garbage value.
an uninitialized local variable's value is undefined. while the static or global will grantee to be 0.
it is a good practice to initialize all variable you defined, otherwise, it may result very very trick bug.
Contrary to your understanding, the content of an uninitialized pointer is undefined. Only if the object is statically allocated is it guaranteed to be zero initialised.
if I initialize a pointer with NULL, is that wrong? What problems do i face? Or it's simply bad programming?
int a,b,*ptr;
ptr = NULL;
ptr=&a;
Is there any problem with the above lines??
In the code that you provided the assignment of NULL is useless, because the pointer is never accessed between the two assignments (i.e. assigning a NULL and an assignment of &a). However, there are other situations when assigning NULL to a pointer is very desirable:
If an assignment of a memory location to a pointer happens conditionally, and then the pointer is passed to free at the end, you need to assign NULL to the pointer at initialization
When a pointer is deallocated with free, but remains visible for some additional time, you should set the pointer to NULL after freeing it to avoid dangling references
When a situation can arise when a pointer is accessed after becoming invalid, you need to assign NULL to the pointer so that your program fails as fast as possible.
This question already has answers here:
Freeing allocated memory: realloc() vs. free()
(7 answers)
Closed 9 years ago.
I have tried freeing memory without using free() as below
int *ptr = malloc(20);
realloc(ptr, 0);
Will it work?
C language standards differ on this one: in C90 passing zero size was the same as calling free:
If size is zero, the memory previously allocated at ptr is deallocated as if a call to free was made, and a null pointer is returned.
However, this changed in C99:
If size is zero, the return value depends on the particular library implementation: it may either be a null pointer or some other location that shall not be dereferenced.
Note that freeing is no longer a requirement; neither is returning a NULL when zero size is passed.
realloc(ptr, 0) is not equivalent to free(ptr)
The standard C11 says:
If the size of the space requested is zero, the behavior is implementation-defined:
either a null pointer is returned, or the behavior is as if the size were some
nonzero value, except that the returned pointer shall not be used to access an
object.
Why because realloc does below things,
It creates new memory of size specified.
Copies contents from old memory to newer.
Frees the old memory
Returns address of new memory
Maybe, but you can't count on it. From the docs:
If new_size is zero, the behavior is implementation defined (null pointer may be returned, or some non-null pointer may be returned that may not be used to access storage).
At least for POSIX: realloc(p, 0) is not the same as free(p).
From the current POSIX documentation on realloc():
Previous versions explicitly permitted a call to realloc (p, 0) to free the space pointed to by p and return a null pointer. While this behavior could be interpreted as permitted by this version of the standard, the C language committee have indicated that this interpretation is incorrect.