expected segmentation fault while incrementing NULL pointer - c

I was expecting the below code to give segmentation fault. Since NULL pointer points to nothing, incrementing something that points to nothing is meaningless.
But its printing 0,4,8,12,16.
#include<stdio.h>
int main()
{
int *p ,i=0;
p = NULL;
for(i=0;i<5; i++) {
printf("%d\n",p++);
}
return 0;
}

You're not dereferncing p, you're converting it's stored value to an int. If you where doing:
printf("%d\n",*p++);
then you'd seg fault.

NULL pointers cannot be dereferenced (which you don't do).
Rather, you are passing the pointer to printf inside an ellipsis, and printf thinks it is dealing with an integer, implicitly performing an unsafe cast (thus your program is also invoking undefined behaviour).

Your program has undefined behavior: ++ operator is only allowed for pointers that point to a valid object and in addition you are passing a pointer value to printf where the format specifies int.
Undefined behavior may result in anything, even that your program seems to work. C doesn't impose any compile time or runtime check for such code. Don't do it.

Related

Constant Value assignment to Integer Pointer in C works for this case

I got an surprising observation, the following code is getting a Segmentation Fault
#include<stdio.h>
void main() {
int *i;
*i = 100;
printf("%u\n",i);
printf("%d\n",*i);
}
But not the below one.
#include<stdio.h>
void main() {
char* str;
int *i;
*i=100;
str = "Hello";
printf("%u\n",i);
printf("%s %d\n",str,*i);
}
Can Someone explains the behavior? I'm using gcc.
First of all, both the snippets cause undefined behavior because of the dereference of uninitialized pointer i.
In your first case, you're trying to dereference an uninitialized pointer i, so that is undefined behavior.
You're doing
*i = 100;
but think, where does i point to? Probably to some memory location which is not accessible from the process, so it is invalid memory access. This triggers the UB.
Same in the second snippet, too.
However, if you remove the usage of i from the second snippet, it will be OK.
After the proposed change, in the second snippet, you're storing the starting address of the string literal into the pointer variable, i.e, assigning it. So, it is perfectly OK.
For a statement like
str = "Hello";
you're not defererencing str here, rather, assigning a pointer value to str, which is perfectly fine.
That said,
according to the C standard, for a hosted environment, void main() is not a conforming signature, you must use int main(void), at least.
A statement like printf("%u\n",i); also invokes undefined behaviour in it's own way. In case you want to print the pointer, you must use the %p format specifier and cast the argument to void*.
Your both programs will cause undefined behavior because of following reasons.So will not get the correct result.
1) Dereferencing uninitialized pointer *i = 100; is undefined behavior . In your both examples you are dereferencing pointer i before initializing it. Therefore first initialize pointer using & operator and after use it in your code.
2) Printing a pointer value using the conversion specifier for an unsigned. You should use %p instead.
i has not been initialized to point to any memory location in particular, so it is not a valid pointer value. Attempting to write through an invalid pointer leads to undefined behavior, meaning the result can be anything - your code may crash outright, it may corrupt data, it may have garbled output, or it may appear to work with no issues.

C pointer initialization differences

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.

Why does malloc work with zero size? [duplicate]

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).

Directly declare and assign value to C pointers

I have read
Directly assigning values to C Pointers
However, I am trying to understand this different scenario...
int *ptr = 10000;
printf("value: %d\n", ptr);
printf("value: %d\n", *ptr);
I got a segmentation fault on the second printf.
Now, I am under the impression that 10000 is a memory location because pointers point to the address in the memory. I am also aware that 10000 could be anywhere in the memory (which might already be occupied by some other process)
Therefore, I am thinking so the first print is just saying that "ok, just give me the value of the address as some integer value", so, ok, I got 10000.
Then I am saying "ok, now deference it for me", but I have not put anything in it so (or it is uninitialized) so I got a segmentation fault.
Maybe my logic is already totally off the track and this point.
UPDATED::::
Thanks for all the quick responses.. So here is my understanding.
First,
int *ptr = 10000;
is UB because I cannot assign a pointer to a constant value.
Second, the following is also UB because instead of using %p, I am using %d.
printf("value: %d\n", ptr)
Third, I have given an address (although it is UB), but I have not initialized to some value so, the following statement got seg fault.
print("value: %d\n", *ptr)
Is my understanding correct now ?
thanks.
int *ptr = 10000;
This is not merely undefined behavior. This is a constraint violation.
The expression 10000 is of type int. ptr is of type int*. There is no implicit conversion from int to int* (except for the special case of a null pointer constant, which doesn't apply here).
Any conforming C compiler, on processing this declaration, must issue a diagnostic message. It's permitted for that message to be a non-fatal warning, but once it's issued that message, the program's behavior is undefined.
A compiler could treat it as a fatal error and refuse to compile your program. (In my opinion, compilers should do this.)
If you really wanted to assign ptr to point to address 10000, you could have written:
int *ptr = (int*)10000;
There's no implicit conversion from int to int*, but you can do an explicit conversion with a cast operator.
That's a valid thing to do if you happen to know that 10000 is a valid address for the machine your code will run on. But in general the result of converting an integer to a pointer "is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation" (N1570 section 6.3.2.3). If 10000 isn't a valid address (and it very probably isn't), then your program still has undefined behavior, even if you try to access the value of the pointer, but especially if you try to dereference it.
This also assumes that converting the integer value 10000 to a pointer type is meaningful. Commonly such a conversion copies the bits of the numeric value, but the C standard doesn't say so. It might do some strange implementation-defined transformation on the number to produce an address.
Addresses (pointer values) are not numbers.
printf("value: %d\n", ptr);
This definitely has undefined behavior. The %d format requires an int argument. On many systems, int and int* aren't even the same size. You might end up printing, say, the high-order half of the pointer value, or even some complete garbage if integers and pointers aren't passed as function arguments in the same way. To print a pointer, use %p and convert the pointer to void*:
printf("value: %p\n", (void)ptr);
Finally:
printf("value: %d\n", *ptr);
The format string is correct, but just evaluating *ptr has undefined behavior (unless (int*)10000 happens to be a valid address).
Note that "undefined behavior" doesn't mean your program is going to crash. It means that the standard says nothing about what will happen when you run it. (Crashing is probably the best possible outcome; it makes it obvious that there's a bug.)
No, the definition int *ptr = 10000 does not give undefined behaviour.
It converts the literal value 10000 into a pointer, and initialises ptr with that value.
However, in your example
int *ptr = 10000;
printf("value: %d\n", ptr);
printf("value: %d\n", *ptr);
both of the printf() statements give undefined behaviour.
The first gives undefined behaviour because the %d format tells printf() that the corresponding argument is of type int, which ptr is not. In practice (with most compilers/libraries) it will often happily print the value 10000, but that is happenstance. Essentially (and a little over-simplistically), for that to happen, a round-trip conversion (e.g. converting 10000 from int to pointer, and then converting that pointer value to an int) needs to give the same value. Surviving that round trip is NOT guaranteed, although it does happen with some implementations, so the first printf() might APPEAR well behaved, despite involving undefined behaviour.
Part of the problem with undefined behaviour is that one possible result is code behaving as the programmer expects. That doesn't make the behaviour defined. It simply means that a particular set of circumstances (behaviour of compiler, operating system, hardware, etc) happen to conspire to give behaviour that seems sensible to the programmer.
The second printf() statement gives undefined behaviour because it dereferences ptr. The standard gives no basis to expect that a pointer with value 10000 corresponds to anything in particular. It might be a location in RAM. It might be a location in video memory. It might be a value that does not correspond to any location in memory that exists on your computer. It might be a logical or physical memory location that your operating system deems your process is not allowed to access (which is actually what causes an access violation under several operating systems, which then send a signal to the process running your program directing it to terminate).
A lot of C compilers (if appropriately configured) will give a warning on the initialisation of ptr because of this - an initialisation like this is easier for the compiler to detect, and usually indicates problems in subsequent code.
This may cause undefined behavior since the pointer converted from 10000 may be invalid.
Your OS may not allow your program to access the address 10000, so it will raise Segmentation Fault.
int *x = some numerical value (i.e. 10, whatever)
may be for microcomputers or low-level (example: creating OS).

Can pointers behave as variable?

I have a confusion related to this program.
#include <stdio.h>
int main(void)
{
int value = 10;
char ch = 'A';
int* ptrValue = &value;
char* ptrCh = &ch;
int* ptrValue1 = value;
char* ptrCh1 = ch;
printf("Value of ptrValue = %d and value of ptrValue1 = %d\n", *ptrValue, ptrValue1);
printf("Value of ptrCh = %c and value of ptrCh1 = %c\n", *ptrCh, *ptrCh1);
}
I get two warnings while compiling this program
unipro#ubuguest:/SoftDev/ADSD/Module
1/Unit 1/Rd/C/System$ cc
charPointers.c -o charPointers
charPointers.c: In function
‘main’: charPointers.c:11:
warning: initialization makes pointer
from integer without a cast
charPointers.c:12: warning:
initialization makes pointer from
integer without a cast
And I know what they mean.
While running the program I get the following error.
unipro#ubuguest:/SoftDev/ADSD/Module
1/Unit 1/Rd/C/System$
./charPointers Value of ptrValue
= 10 and value of ptrValue1 = 10 Segmentation fault
I know I am getting the error at second printf method.
So my question is if I store a value in pointer, why can't we de-reference it? Does it behave like a variable?
Thanks.
With the assignment
char* ptrCh1 = ch;
you will set the address to 0x41, not the value. The program will later try to de-reference 0x41 (ie. fetch the data at adress 0x41), which is an illegal address. Hence, the segmentation fault
A pointer store the address of something (or NULL). Thus an int* can store the address of an int. You get the address of something with the unary & operator.
So, what does it mean to store 10 in an int pointer ? Well, 10 is not the address of an int, so thus you get the "initialization makes pointer from integer without a cast" warning, and since you are storing something else than the address of an int in an int* and try to dereference it, you get undefined behavior.
What's likely occuring in your case is 10 gets interpreted as a memory address, and when you dereference a pointer it goes out to fetch whatever is at that address (memory address 10 in your case). There's likely nothing there, that memory area is not mapped, and you segfault.
You can dereference it, but the chances that you get a valid chunk of memory are pretty slim. Valid here means, that your process has access rights to that spot.
The OS will prevent you from modifying memory that does not belong to your process. It responds to that kind of invalid memory access with a segmentation fault "exception".
A pointer points to a memory location (in which you can then store some value). Here
int* ptrValue1 = value;
char* ptrCh1 = ch;
you assign a pointer to the value of a variable (not to its address), so the pointer most likely points to an invalid memory location, thus the segfault.
Note that in many architectures, valid memory locations start at a high offset, so a small integer value like 10 or (the ASCII value of) 'A' can never point to a valid memory location. Such low memory locations are typically reserved/used by the OS itself (thus they are protected from modification - if you try, you get a segfault). The same happens usually if you try to directly access memory used by another process.
It's because of *ptrCh1 in the last line, you are trying to dereference it. Remove the * to make it work (not that it makes much sense, though).
Sure that it must segfault. Your are storing whatever value in a pointer (and as you say the compiler warned you) and then you dereference it, regardless where this points to.
What else do you expect?

Resources