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.
Related
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.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Can we assign or compare a valid pointer with 0? where could we assign NULL as legal?
See what I know NULL is a invalid pointer , that pointing to heap memory , which pointer has not freed yet.But is the address of the pointer is valid?
NULL as a pointer valid address?
Maybe: NULL is a macro which expands to a null pointer constant. It may have a value like int 0. In that case, it is not a pointer but a int. It may have a value like ((void*)0) which is a pointer. When a null pointer constant is converted to void *, it is a null pointer. No object will have an address that is equal to a null pointer. The null pointer can be assigned to any pointer variable.
Can we assign or compare a valid pointer with 0?
Yes. any_type *ptr = 0; is valid. The comparison if (ptr == 0) is valid. The int 0 is converted to a null pointer as part of the assignment / compare.
where could we assign NULL as legal?
any_type *ptr = NULL; is a legal assignment.
See what I know NULL is a invalid pointer , that pointing to heap memory , which pointer has not freed yet. But is the address of the pointer is valid?
The address is or is not valid is irrelevant. Pointing to heap memory or not is irrelevant. In C, assigning a null pointer to a pointer variable is valid. Comparing a null pointer to a valid object is a valid comparison and the result never matches.
Dereferencing a pointer that has the value of a null pointer is undefined behavior (UB). It may "work", it may crash the code. It is UB.
NULL is the null pointer constant, it's value is implementation defined, that is to say, it is not necessarily being 0.
According to the C11 standard,
Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
In addition, assign integers to pointers is implementation defined, you should not rely on it if you want to make portable code.
An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
No, NULL does not denote a valid address in any way. NULL is a MACRO which is basically an implementation defined null pointer constant.
Related, C11, chapter 7.19,
NULL
which expands to an implementation-defined null pointer constant
It will compare unequal to any valid pointer and any attempt to derefernce a pointer initialized with NULL will result in UB.
Quoting C11, chapter ยง6.3.2.3
If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
NULL is by definition an invalid pointer. But. On most systems pointers are just numbers that we give a special treatment. Until a while ago (maybe a decade or so) it was possible on some operating systems to forcibly map memory at the address where a NULL pointer pointed.
This led to a dangerous situation where the operating system kernel could have a relatively harmless bug that led to a NULL dereference and normally just crash. But instead, if a malicious program forcibly mapped memory at the NULL address and then triggered the kernels NULL dereference, it would point to valid memory and if done correctly it could escalate a simple system crash to a kernel level privilege escalation.
There was a bug in Linux where a driver could be fooled into executing a NULL function pointer and that allowed a malicious program to put code at that address that the kernel would execute with raised privileges.
Since then most operating systems have tightened their security and disallow mapping any valid memory at the addresses at and close to NULL ("close to" to protect against array access with a large offset through a NULL pointer).
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.
As robustness and best practices, If a pointer to any data type will be accessed, we should protect it against being NULL before accessing...
for example:
int Var;
int *ptrToVar = &Var;
int main(void)
{
if (ptrToVar != NULL)
{
(*ptrToVar) = 6;
}
else
{
//do nothing
}
}
My question is:
Is it possible for ptrToVar to be NULL during the run time of code?
If yes! So What can make the pointer ptrToVar be NULL during run time?!
Global variables are stored in the data-segment. If the global variables are not initialized they will be intiialized to 0 . So it is just the initialization which will be to 0. You have a pointer ptrToVar pointing to this variable. So this pointer can never be NULL unless there is some unallocated memory access or UB in your code.
You can try and print the address the pointer is pointing to it can't be NULL.(In a defined behavior).
If we just consider the code which you have posted the pointer ptrToVar is not NULL.
It can only be NULL if your program has undefined behavior. In a correct C program a local variable will never be NULL. Therefore the check is not needed.
6.3.2.3 Pointers
p2: An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant. If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
If your program has bugs, use assert() to locate them, it will print a warning and abort immediately.
In your code int *ptrToVar = &Var ptrTovar is having the address of var.
Hence it has the address of the var, the ptrTovar will not be NULL.
if the ptrTovar is a global variable or if you have initialized the ptrTovar as NULL, then the address will be NULL.
if you print printf("address:%d\n",ptrTovar), it will print some address, so it not NULL in your code.
I have a pointer that is pointing to the start of an array, but I need to check that it is unallocated. I thought of dereferencing the pointer and checking if NULL but that leads to a type error. Can anyone see what I'm doing wrong?
int mydispose(int *array){
int i = 0;
if(*array == NULL){
return 1;
}
return ;
}
EDIT: Sorry if I was unclear: I have a pointer that points to the start of an array, but I wish to check whether the array is empty.
*array == NULL is wrong. You are dereferencing the pointer first (which could lead to a segfault if the pointer really is null) and then comparing its int value to a pointer value. Moreover, your compiler will perfectly accept that erroneous expression if NULL is defined as just 0 and not (void *) 0.
You should be checking array == NULL to see if the passed pointer refers to anything, and then dereference it only in case it's not NULL.
Be aware, however, that dereferencing a non-null pointer isn't guaranteed to be a safe operation either. If the pointer contains a garbage value because it was allocated on the stack and not initialized, or if it refers to a deallocated region of memory, nasty bugs can happen.
You want if (array == NULL) -- but unless you first initialize array to NULL, it won't do any good either. I think you'd be better off backing up and telling us a bit more about what you're trying to accomplish, and trying to get help trying to accomplish your overall goal.
The only safe way to determine the allocation status of *array is to:
Make sure *array is set to NULL is not allocated. int *array = NULL;
Check if the array is NULL: if (array == NULL) return -1;
You can't reliably check if some memory location is allocated. *array is not a valid code, because it's the same as array[0], but array[0] is not allocated. Non-allocated memory location can contain any value.
The only option is to ensure that you get the information whether the array is allocated alongside with your array. A popular option is representing unallocated array as NULL, but you may choose other option as well.
By the way, there is a difference between an empty array (that is, array of size 0), and array which is not allocated at all. The first option occurs when you use malloc(0), the second when your pointer is not initialized at all. For malloc(0) it's allowed to return NULL, but it's allowed to return a non-NULL pointer (which you however can't dereference) as well. Both ways are valid according to the standard.
The immediate problem with your code is that you dereferencing array before comparing it to NULL. The type of the expression *array is int, not int *. Leave off the dereference operator and the types will match:
if (array == NULL) {...}
Note that an uninitialized pointer is only guaranteed to contain NULL if it was declared with static extent (i.e. it was either declared at file scope or with the static keyword in front of it). Similarly, calling free on a pointer won't set that pointer value to NULL; it will contain the same pointer value as before, but it will now be invalid.
You must use it like this:
if(array == NULL) ...