rr-
rr-

Reputation: 14811

Reason why this reinterpret_cast crashes

Background: I work a lot with binary data, and I often need to work with raw pointers. I also often need the size so that I can check if I read/write off the bounds (reasonable, right?). Now I'm trying to create a syntactic sugar class for pointers that holds size of the underlying data so that I can simplify function declarations.

Demonstration of the problem - the code behind my class that crashes can be simplified to this:

char *a = (char*) malloc(4); // some underlying data
strncpy(a, "1234", 4); // that is not statically linked so it can be written to

uint32_t *ptr = reinterpret_cast<uint32_t*>(a);

ptr[0] = 1234; // works
reinterpret_cast<int&>(ptr[0]) = 1234; // curiously, this works too
*reinterpret_cast<int*>(ptr[0]) = 1234; // this crashes the program

printf("%d\n", ptr[0]);

The program above crashes as described in comments. Valgrind outputs following:

Invalid write of size 4
   at 0x40064A: main (in /home/rr-/test)
 Address 0x4d2 is not stack'd, malloc'd or (recently) free'd

I suspect I'm violating the strict aliasing rule, but:

  1. I made sure to use char* for underlying structure. Most likely, it doesn't matter because what I'm reinterpret_casting isn't a char* but a uint32_t* and compiler doesn't care what uint32_t* originally pointed at.
  2. But even if I play with -fno-strict-aliasing and -fstrict-aliasing, the program crashes all the same... (I compile the program with g++ 5.2.0 under GNU/Linux.)

Can someone tell where did I go wrong, and how can I correct this problem?

Upvotes: 0

Views: 1356

Answers (1)

Bo Persson
Bo Persson

Reputation: 92271

You just stored 1234 in ptr[0]. Then you cast the 1234 into a pointer and dereference it.

That tries to access address 1234, which doesn't work.

Upvotes: 1

Related Questions