Is dereferencing illegal without referencing? - c

I tried storing a value in an uninitialized pointer using the following code but got segmentation fault (core dumped error ).
#include <stdio.h>
int main()
{ const int a=9;
int *p=&a;
scanf("%d",p+1);
printf("%d %d",*p,*(p+1));
return 0;
}
please explain why? Noob here

I tried storing a value in an uninitialized pointer
This is an initialized pointer: int *p=&a;
However, you cannot assign a const int* to an int* in C, it is invalid code and will not compile cleanly.
scanf("%d",p+1);
The code p+1 points out of bounds of the allocated variable. You tell scanf it's ok to store something at an address where no memory is allocated. This is undefined behavior and may crash.
*(p+1)
Here you de-reference the pointer, again one item out of bounds. This is not allowed - it is undefined behavior and could cause a crash.

You have problem in
scanf("%d",p+1);
you are not allowed to access the memory location as p+1, it's outside the legally accessible memory by your program, in other words, invalid memory location. Attempt to access (read/write) invalid memory location invokes undefined behaviour.

Related

Segmentation fault: but why?

#include <stdio.h>
int main()
{
int* ptr;
*ptr = 5;
printf("%d", &ptr);
return 0;
}
This was asked in a coding interview, what should be the output?
I am confused between runtime error, compilation error and segmentation fault.
Anyone who can explain why will the answer be segmentation fault?
Your code invokes undefined behavior because the pointer was left uninitialized. You need to initialize the pointer first before inserting into it anything:
int *ptr = malloc(sizeof(int) * REQ_SIZE);
After this, you will no longer get a segfault. Note that you need to put a dereference operator instead of & to print the containing value of the integer pointer.
Here's a demo.
Compilation error is an error that you face while your program is being compiled by the compiler and it's due to C grammar (Maybe you wrote an incorrect instruction grammatically.)
Runtime error is an error that you face when your program is running.
Segmentation fault is an error that you face when you're trying to access to a location in the memory that you're not allowed to access to it such as a location indicated by null pointers.
Your program has undefined behavior. Because pointers store a memory address and they cannot store a value such as a number. You could allocate some memory from heap and then you can store a value in your pointer:
int *ptr = (int*) malloc (sizeof(int));
*ptr = 5;
Or you could declare a local variable and store its address in ptr:
int value = 5;
int *ptr = &value;
Just look at the definition of Pointers. Pointer is a variable whose value is the address of another variable, i.e. direct address of the memory location. Here in your case, ptr is declared as an integer pointer, which isn't pointing to any address. That's why it gives Segmentation Fault Error. Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you". Instead of this you can do 2 things :
Assign a new integer variable's address to the pointer :
int x;
int *ptr = &x;
*ptr = 5;
Initializing the pointer using the malloc() :
int *ptr = (int*)malloc(sizeof(int) * SIZE_REQUIRED);
Also note that by using the reference of ptr in the printf() prints the address of the pointer rather than the value contained by the address it is referring to. It is demonstrated here :
printf("%d", ptr); // Prints the address of the pointer variable.
printf("%d", *ptr); // Prints the value (in this case : 5) contained by the address referenced by the pointer.

Can anyone explain to me what actually causes this Segmentation Fault and How to overcome this?

#include <stdio.h>
#define null1 ((void*)0)
#define val ((int)2)
int main() {
int *p;
p = null1;
printf("%p", &p);
//p = (int *)val;
*p = val;
//printf("\n%p", (int*)p);
return 0;
}
Output:
Segmentation fault(core dumped)
I want to assign value of macro to the Pointer.
null1 is a null pointer, its definition #define null1 ((void*)0) is one of the accepted definitions for a null pointer.
val is a macro expanding to the plain integer constant 2. Casting 2 as (int) has no effect, 2 is already an int constant value.
Storing a value to a null pointer has undefined behavior. A segmentation fault is one the possible effect of undefined behavior. A rather useful one since it allows the debugger to point to the problem immediately.
Casting any other integer value as (int *) has undefined behavior too: p = (int *)val; *p = val; is very likely to cause the same segmentation fault, but may have some other unexpected side effects, depending on the target platform specifics: if 2 happens to be the address of the self-destruct trigger port, all bets are off.
Null pointer is a special reserved value of a pointer. A pointer of any type has such a reserved value. Formally, each specific pointer type (int *, char * etc.) has its own dedicated null-pointer value. Conceptually, when a pointer has that null value it is not pointing anywhere.
Void pointer is a specific pointer type - void * - a pointer that points to some data location in storage, which doesn't have any specific type.
Here null1 refers to a void pointer whereas p is a pointer of the type integer.
Hope I was right and this is helpful to you.
Pointers directly point to memory addresses. While each program that we run is allocated a fixed memory area only (called segments). All memory address in this area is referred to using relative memory address.
But pointers have absolute memory addresses in them. Generally, the starting memory addresses are for Operating System's use. When you assign a pointer to some address outside of its segment area then it gives SIGSEGV ( Segmentation Error ).
In your case also, you are trying to assign p an address outside its segment area thus the error.
NULL pointer is an invalid pointer because it points to memory that is not valid to access so that the statment *p = val is not valid, so the Segmentation fault error appears.
To overcome this error you need to assign a valid address of a memory location to the pointer(p), such as defining a variable (var) and assign the addres to the pointer as p = &var;.
You just need to assign your pointer to your macro as code below:
#include <stdio.h>
#define val 2
int main()
{
int *p;
p = (int*)val;
printf("%p\n", &p);
printf("%d\n", p);
return 0;
}

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.

Is it legal C to use an address that has not been allocated?

I don't know much about how memory allocation actually works, but what would be the problem with this:
int main(){
int a=1;
int *p = &a;
p++;
*p = 2;
printf("%d", *p);
return 0;
}
In general it yields undefined behavior, often leading to a memory access violation.
In your example, however, it might work fine since variable p is possibly located immediately after variable a in the stack (subjected to the compiler that you are using), so by incrementing the value of variable p you are essentially setting it to point to itself.
Now, if sizeof(p) == sizeof(*p), i.e., if sizeof(int*) == sizeof(int), which happens to be the case on many compilers (where both are equal 4), then when you write a value into the address pointed by p, you are setting both p and *p to that value.
Please note that any subsequent attempt to write a value into the address pointed by p, will be equivalent to writing a value into address 2 in the memory space of your program, and this time it will most likely lead to a memory access violation.
No. It is not legal to use unallocated memory location to read or write. It invokes undefined behavior
You are overwriting memory you did not allocate by yourself. This infers undefined behavior, which is by definition not good and thus "not legal".
One should never try to access a memory which is not defined/allocated by yourself as this can lead to something unpredictable.
This would not give syntax error but runtime errors can be generated.
So always make sure before accessing a memory that it has been allocated by you only.

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