This question already has answers here:
What exactly is meant by "de-referencing a NULL pointer"?
(8 answers)
What happens in OS when we dereference a NULL pointer in C?
(5 answers)
Closed 4 years ago.
Just a curious question. What happens if i try to access data from an address that has NULL value.
for eg: If i have a structure pointer ulog which stores NULL and the compiler (in my case GCC) comes across ulog->data=12 ?
I wanna know majorly if this messes with my memory, is NULL returned when used with control statement and what goes down with the compiler ?
To clear out the terms:
The macro NULL is a null pointer constant (7.19/3).
A null pointer constant is either the value 0 or (void*)0 (6.3.2.3/3).
When a null pointer constant is assigned to a pointer of any type, the resulting pointer becomes a null pointer which is guaranteed to compare unequal to any other pointer (which is pointing to an object or function) (6.3.2.3/3).
You can't really know the actual representation of a null pointer on the given system. What happens if you try to access it as if it was a valid address is not specified by the standard - it is undefined behavior.
Meaning that anything can happen, including segmentation faults, bus errors, nothing at all, program starting to run amok etc etc.
The compiler won't complain.
However, in runtime, you will invoke Undefined Behavior (UB), since you are dereferencing a NULL pointer.
Related
I am new to C and have some questions about the pointer.
Question 1 What`s differences b/w the following two? Which way is better to initialize a pointer and why?
int *p=NULL;
int *p;
#include <stdio.h>
void main()
{
char *s = "hello";
printf("%p\t%p",s);
//printf("%p\t%p",&s) it will give me unpredictable result every time
//printf("%p\t%p",(void *)&s) it will be fine
//Question3: why?
}
Question 2: I try to google what is %p doing. According to my reading, it is supposed to print the pointer. It that mean it print the address of the pointer?
Question 1, these are definitions of pointer p. One initializes the pointer to NULL, another leaves it uninitialized (if it is local variable in a function, and not global variable, global variables get initialized to 0 by default). Initializing with NULL can be good, or it can be bad, because compiler can warn you about use of uninitialized variables and help you find bugs. On the other hand compiler can't detect every possible use of uninitialized variable, so initializing to NULL is pretty much guaranteed to produce segmentation fault if used, which you can then catch and debug with a debugger very easily. Personally I'd go with always initializing when variable defined, with the correct value if possible (if initialization is too complex for single statement, add a helper function to get the value).
Question 2, %p prints the address value passed to printf. So printf("%p", pointer); gets passed value of variable pointer and it prints that, while printf("%p", &pointer); (note the extra & there) gets passed address of the variable pointer, and it prints that. Exact numeric format of %p is implementation defined, it might be printed just as a plain number.
Question 3 is about undefined behavior, because format string has more items than what you actually pass to printf. Short answer is, behavior is undefined, there is no "why". Longer answer is, run the application with machine code debugger and trace the execution in disassembly view to see what actually happens, to see why. Note that results may be different on different runs, and behavior may be different under debugger and running normally, because memory may have different byte values in different runs for various reasons.
1) The first is an initialization (to NULL in this case) the second is only a declaration of p as a pointer to int, no initial value is assigned to p in this case. You should always prefer an initialization to prevent undefined behavior.
2) You should cast to void* when using %p to print out a pointer (beware that you are using it too many times in your format specifier). The memory address to which p points is printed.
1)
int *p = NULL
defines and initializes a pointer 'p' to NULL. This is the correct way to initialize pointers in order to get "Seg Fault" if you forget to assign a valid address to this pointer later.
int *p
Only defines a pointer "p" with an unknown address. If you forget to assign a valid value to this pointer before using it, then some compilers will notify you about this mistakes while some others will not and you may access a non-valid address and get a run time error or undefined behaviour of the program.
2) "%p" is printing the address where the pointer is points. Since the pointer holds an address, then "%p" prints this address.
printf("%p\t%p",s);
So the first "%p" will print the address where the pointer "s" points which is the address which stores the string "hello". However, note that you are using twice "%p" but you providing only one pointer to print its address !!
Most compilers will not scream about this cause it is effect-less; however try to avoid it.
Answer1 :
int *p=NULL;
p is a pointer to a int variable initialized with NULL. Here NULL means pointer p is not pointing to any valid memory location.
int *p;
p is a pointer to a int variable. p in uninitialized. Reading uninitialized variables is Undefined Behavior. (one possibility if try to use is that it will throw a segmentation fault)
Answer2:
It prints content of pointer. I mean base address of string "hello"
The main difference is that in *p = NULL, NULL is a pre-defined and standard 'place' where the pointer points.
Reading from Wikipedia,
The macro NULL is defined as an implementation-defined null pointer constant,
which in C99 can be portably expressed as the integer value 0
converted implicitly or explicitly to the type void*.
This means that the 'memory cell' called p contains the MACRO value of NULL.
If you just write int *p, you are naming the memory cell with the name p but this cell is empty.
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).
This question already has answers here:
behaviour of malloc(0)
(3 answers)
Why does strcpy "work" when writing to malloc'ed memory that is not large enough? [duplicate]
(5 answers)
Closed 7 years ago.
This is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* p;
p = (char*)malloc(0);
scanf("%s", p);
printf("%s", p);
free(p);
}
Could someone explain to me why every word i am typing via terminal is printed out to the user? I have malloc(0). Isn't supposed when i try to scanf to give me a segmentation fault?
Edit
Why this gives me a compilation error:
p = malloc(sizeof(char) * 2)
when i try to to avoid (void*)
error: cannot initialize a variable of type 'char *' with an rvalue of type 'void *'
The C Standard for malloc explicitly specifies this:
If the size of the space requested is 0, the behavior is
implementation-defined: the value returned shall be either a null
pointer or a unique pointer.
And for the return value from malloc:
If size is 0, either a null pointer or a unique pointer that can be
successfully passed to free() shall be returned. Otherwise, it shall
return a null pointer and set errno to indicate the error.
In regards to segmentation fault from the call to scanf, that is purely on the basis of the implementation and runtime behaviour of the environment, just down to luck rather than anything, the next time it is run, it may crash with segmentation fault.
The C standard 9899:2011 7.22.3 states that:
If the space cannot be allocated, a null pointer is returned. 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.
Meaning that what is returned from malloc is implementation-defined behavior. You'll have to read your specific compiler documentation to see what it does in your case: return a null pointer or a non-zero pointer pointing at 0 bytes of data (likely a random garbage location).
In either case, the returned pointer is not pointing at a valid memory location. So if you attempt to write to it, you'll invoke undefined behavior. Meaning anything can happen: the program can crash & burn, or it can seem to work correctly and crash one month later, or anything else.
Why this gives me a compilation error: p = malloc(sizeof(char) * 2)
Because you are trying to compile C code with a C++ compiler. Don't do that. Some C++ compilers have an option you can set to compile with a C compiler instead.
Side note about an inconsistency in the C standard:
The standard Annex J actually list the above as unspecified behavior. I suspect this must be an error in Annex J, as the normative text cited above clearly states that this is implementation-defined. 7.22.3 is normative and Annex J is informative, so I would just ignore Annex J.
From opengroup -
If the size of the space requested is 0, the behavior is implementation-defined: the value returned shall be either a null pointer or a unique pointer.
Nothing is allocated by malloc(0). So , when you try to take input using scanf you invoke undefined behaviour .
Isn't supposed when i try to scanf to give me a segmentation fault?
No , it's not necessary when you have UB . Maybe you are not that lucky to get segmentation fault and got desired output( which may confuse).
This question already has answers here:
What is the difference between NULL, '\0' and 0?
(11 answers)
Closed 9 years ago.
As far as i know, the NULL is actually not 0. So is there any difference in comparing a pointer with 0 or with NULL?
Further what should be the correct usage. Thanks!
The correct usage is to use NULL : It's more readable (p = NULL -> you know that p is a pointer)
In C,the macro NULL is defined as an implementation-defined null pointer constant, which in C99 can be portably expressed as the integer value 0 converted implicitly or explicitly to the type void*.
In C++ NULL is the integer literal for zero (0 or 0L) has been traditionally preferred to represent a null pointer constant.
Compiler would implicitly convert 0 to NULL in case of comparison with a pointer.
It is always safe to compare 0 with NULL.
NULL is not necessarily 0 and should only be used for pointers.
NULL is a macro usually defined as (void*)0 but not always.
It's a pointer to no location in memory.
There's a very good new book called Understanding And Using C Pointers. Please read that one.
Don't use it for anything but pointers.
Recently I saw following piece code:
if ((rgb = (fp16 *)malloc(width*height*sizeof (*rgb)*3)) == NULL)
rgb is declared as a pointer of some class type.
In the above code, malloc() is taking arguments which is width*height*sizeof(*rgb)
So it is some kind of self referential initialization(If i may call it by giving this name!)
i.e. belore rgb pointer is allocated by malloc, it is dereferencing it in call to malloc.
In this particular code, i saw that the pointer rgb is not initialized to NULL or anything.
What would be the behaviour of such code.
Normal functioning or
Crash due to null pointer dereference, or a
Garage pointer dereference
thanks,
-AD.
sizeof does not evaluate its operand, so in this case sizeof(*rgb) will return the size of rgb's type, which I assume is fp16 *.
Completely valid C code.
If it did evaluate it and the pointer was just some declared pointer with no initialized value, then you would get undefined behavior.
It's not actually dereferencing the pointer, sizeof(*rgb) does a compile-time determination of the size of the type pointed to by rgb. The machine code generated by that line will use a literal number in place of the sizeof(*rgb) term.
sizeof doesn't evaluate its argument. It only computes its size. So you don't get the undefined behaviour associated to uninitialized pointer dereferentiation.
Under normal circumstances, the if block would not happen when malloc succeeds. If malloc fails, the block will be executed.
Quoted:
i saw that the pointer rgb is not
initialized to NULL or anything.
if rgb is initialized to NULL, then it will go through that if condition.
That is code line is fine.