简体   繁体   中英

void pointer typecasting

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

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.

 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM