Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

unexpected address for a referenced indirected pointer in a struct as opposed to same declaration with a plain variable?

I have a struct containing a byte array and several typecast references to various points in the array. Bytes 4:7 may be interpreted as a float, int32_t, or uint32_t as determined by other fields in the packet being received over a serial connection. To make access simple (e.g. message.argument.F for a float interpretation), I made multiple references to indirected typecast pointers. But when I ran the program, I got a segfault trying to write to the references in the struct. As near as I can tell, the problem has to do with the container, as illustrated by this example snippet (cpp shell: http://cpp.sh/3vmoy):

#include <iostream>
#include <cstring>
using namespace std;

#define PACKET_SIZE 9
#define ARG_I 4

struct Message{
  uint8_t bytes[PACKET_SIZE];
  uint8_t* argbytes = static_cast<uint8_t*>(argp);
  float& argf = *static_cast<float*>(argp);
  void* argp = &bytes[ARG_I];
} message;



int main(){
    // USING STRUCT    
    cout << "Using message struct" << endl;
    cout << message.argp << endl;                           // the pointer at index stored in struct
    cout << static_cast<float*>(message.argp) << endl;      // casting the pointer to a float* - should be the same
    cout << &message.argf << endl;                          // the address of the float reference cast from argp, ** should be the same BUT IS NOT **
    
    // RAW VARS
    uint8_t bytes[PACKET_SIZE];
    void* argp = &bytes[ARG_I];
    float& argf = *static_cast<float*>(argp);

    cout << endl << "using raw vars" << endl;
    cout << argp << endl;                                   // a pointer to a byte in an array of bytes.
    cout << static_cast<float*>(argp) << endl;              // the same pointer cast as a float*
    cout << &argf << endl;                                  // the address of a float reference cast from argp, **should be the same AND IS.**
}

I expect to see the same address for the pointer, a typecast pointer, and the address of the reference for the indirected pointer. I do see that if I create an array and the pointer/reference as standalone variables, but not for the same declarations in a struct. What arcane knowledge do I lack to explain this behavior (or what silly thing have I overlooked?)

My thoughts for fixing this are to a) ignore it and just typecast the pointer as necessary instead, or b) make some setter/getter functions to access the argument portion of the serial "packet".

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

There are two major, fundamental differences between the two alternative chunks of code.

    void* argp = &bytes[ARG_I];
    float& argf = *static_cast<float*>(argp);

Here, this constructs and initializes argp first, then argf.

  float& argf = *static_cast<float*>(argp);
  void* argp = &bytes[ARG_I];

And here, it does not.

This initializes argf first, then argp. The consequences of this should be quite apparent.

Note: I’m ignoring all the aliasing rule violations here, that are likely to be a source of further undefined behavior.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading