Reputation: 861
I was trying to understand void pointer typecasting in C. I wrote a program to try and create a segmentation fault, but I am not getting it. Can someone please explain to me why
Code:
#include <stdio.h>
typedef unsigned long U32;
int main()
{
void *obj;
U32 value = 25;
U32* ptr;
printf("*(ptr) : %lu\n", *(ptr));
obj = &value;
ptr = &value;
ptr++;
printf("*(U32 *)(obj) : %lu\n", *(U32 *)(obj));
printf("*((U32 *)(obj) + 1) : %lu\n", *((U32 *)(obj) + 1));
printf("*(U32 *)((U32 *)(obj) + 1) : %lu\n", *(U32 *)((U32 *)(obj) + 1));
printf("*(ptr) : %lu\n", *(ptr));
return 0;
}
Output :
*(ptr) : 458998657
*(U32 *)(obj) : 25
*((U32 *)(obj) + 1) : 3215085752
*(U32 *)((U32 *)(obj) + 1) : 3215085752
*(ptr) : 3215085752
The way I see it only the 2nd printf is legal as all others are referring to some uninitialized random memory and should cause a seg fault
Upvotes: 0
Views: 2882
Reputation: 229058
U32* ptr;
printf("*(ptr) : %lu\n", *(ptr));
ptr
is uninitialized so it is undefined behavior to dereference it,
obj = &value;
ptr = &value;
ptr++;
printf("*(U32 *)(obj) : %lu\n", *(U32 *)(obj));
Ok, as long as obj
is pointing to a valid U32 (and U32 has to be an unsigned long as you're using %lu as the printf format)
printf("*((U32 *)(obj) + 1) : %lu\n", *((U32 *)(obj) + 1));
You're trying to dereference a pointer that points one U32 past any valid location, so it's undefined behavior.
printf("*(U32 *)((U32 *)(obj) + 1) : %lu\n", *(U32 *)((U32 *)(obj) + 1));
Same as above.
printf("*(ptr) : %lu\n", *(ptr));
Since you incremented ptr
, it points one U32 past anything valid, which leads to undefined behavior.
As your code does things that invokes undefined behavior, it's really hard and often impossible to reason about what is going to happen. It's undefined. Something unexpected could happen. Something bad could happen. Nothing bad could happen, and so on. Doing something in C that you should not do, does not mean it will segfault.
Upvotes: 1
Reputation: 146910
UB is funny like that- the behaviour is undefined, not guaranteed segfault. The address of obj + 1
is probably some other spot on the stack which is allocated to your program anyway. To get an almost guaranteed segfault, just de-reference obj
before it has ever been assigned.
Upvotes: 2
Reputation: 145829
ptr
points to a valid object (value
) but ptr++
does not point to an object. So accessing the element *ptr
after the pointer increment is undefined behavior. printf
of *ptr
can display random data but can also crash your program.
Upvotes: 0