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.
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.
#include <stdio.h>
int main(void)
{
int *ptr;
printf("%p", ptr); // Error: uninitialized local variable 'ptr' used
// Output is "0"
}
I'm reading C-FAQ about null pointer. And it says that uninitialized pointer might point to anywhere. Does that mean it points to random location in memory? Also if this statement is true, why does error occur if i try printf("%p",ptr)? Since uninitialized pointer ptr points to some random location, it seems that it must print out this random location!
The contents of an unitialized auto variable (pointer type or otherwise) are indeterminate; in practice, it's whatever was last written to that memory location. The odds that this random bit pattern corresponds to a valid address1 in your program are pretty low; it may even be a trap representation (a bit pattern that does not correspond to a legal value for the type).
Attempting to dereference an invalid pointer value results in undefined behavior; any result is possible. Your code may crash outright, it may run with no apparent issues, it may leave your system in a bad state.
That is, the address of an object or function defined in your program, or a dynamic object allocated with malloc or similar.
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).
I created an array of pointers to char. I used malloc(0) to allocate memory for those pointers.
After that, I used scanf() to enter exactly one word to the bytes allocated by malloc(0 and it worked.
Why is that?
First of all, from the man page for malloc(), (emphasis mine)
If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
So, it's not guaranteed that malloc(0) will return NULL, always. So, your NULL check may not be a success.
Then, to answer
Why is that?
because, in case malloc(0) returns a pointer other han NULL, it is only fit to be used as an argument to a later call to free(), nothing else. In your case, you're trying to write into the memory. Doing so is essentially attempt to write into an invalid memory, a memory which not allocated to your program. This invokes undefined behavior.
The real beauty of UB is that, sometimes, program invoking UB appear to work just fine.
What does the following piece of code mean?
int* pointer = malloc (sizeof(int) + 3);
pointer++;
The allocated piece of memory can't be broken down into chunks of sizeof(int). So what happens when pointer is asked to jump to the next "block"? Is it defined?
The code is valid but maybe unusual without more context.
Line 1: The malloc allocates 3 bytes larger than the size of an int. This is valid.
Line 2: The pointer++ is valid. It's just an address.
Further references to pointer (e.g. addition or subtraction or comparison) are valid. Dereferences (i.e. *pointer) will result in undefined behaviour.
Not that those 3 "extra" bytes are valid storage space and can be addressed with a char *, for example.
pointer can be used for pointer comparison (C standard allows pointers to be one element past the last one). Read or write access is undefined.
*pointer is 3 bytes of 0 and sizeof(int) - 3 bytes of undefined. Which byte[s] (as related to significance in your int) are undefined is platform dependent (on the system bytesex) so in terms of your C program, the whole thing might as well be undefined.