-1

I have a struct that looks like this

struct message_header
{
    unsigned long msg_num : 32;            //0-3    message id
    unsigned long msg_len : 32;            //4-7    message length
    unsigned long hardware_version : 16;   //8-9    hardware version
    unsigned long sender_location : 32     //10-13  location
    unsigned long message;                 //14 ... messages
};

message_header * msg_ptr;

After receiving the character array (recvbuf) from recvfrom function, i will do reinterpret_cast,

msg_ptr = reinterpret_cast<message_header*>(recvbuf)

However, after my simulator (from linux, VM) sends the data, and my receiver (the struct is in the receiver) (on windows), the output data does not tally.

Assuming the data send from the simulator is:

msg num : 1010
msg len : 20
hardware version: 1
location: 25
messages: //rest of the bytes

Packets from the wireshark shows:

00 00 03 F2
00 00 00 14
00 01 00 00
00 19 00 00
...

The output print is:

msg num : 1010
msg len : 20
hardware version: 1
location: 1638400

After much debugging, I noticed that during the cast, after hardware version, the 00 00 after the 01 was either discarded, or skipped, i am not sure which as I can't find a way to determine it, and the next 4 bytes of 00 19 00 00 was cast into my sender_location.

All the message types and length, from the sender is build base on the sender's design specification, and the hardware version on the sender is an unsigned short.

I have read up on the following question and answers

Fields in a struct skipping bytes

#pragma pack effect

And i have tried but to no avail, please advise.

Zac
  • 167
  • 1
  • 2
  • 7
  • Are you using an old compiler that doesn't support [C99 fixed width integer types](http://en.cppreference.com/w/c/types/integer) or can pack structures? Is there some other reason you have a bitfield? – Some programmer dude Jun 01 '17 at 05:10
  • I am using VS 2015, and i am using bitfield to limit on the amount of bytes getting cast into the per variables, i am a junior programmer and using bitfield is "recommended" by my senior, i was initially using memcpy per field but was told that casting it into a struct would be less complicated. – Zac Jun 01 '17 at 05:11
  • As for your problem, have you tried to allocate the message structure separately and then using `memcpy` to copy the data (the whole structure)? – Some programmer dude Jun 01 '17 at 05:12
  • gonna try that now and let you know the result – Zac Jun 01 '17 at 05:14
  • @Someprogrammerdude yes, memcpy, works just fine – Zac Jun 01 '17 at 05:41
  • Then I suggest you use that for now, while you try to figure out why the casting doesn't seem to work (it should, if the buffer is large enough and you don't modify it directly any other way). – Some programmer dude Jun 01 '17 at 05:46
  • i will have to change my entire class, which might be a bit of work, and yes, i do not understand why are my bytes discarded, or not being cast into the variables as well. – Zac Jun 01 '17 at 05:47
  • 1
    Have you checked that the data in the buffer right after you received it is correct? Have you checked the data in the buffer directly before the cast? If it's correct at either point then it might be a compiler bug. If the data is incorrect when cast it, but correct when receive it, then it's modified somewhere between and you have to look at that code. It could also be problems with threads overwriting data perhaps? There could be thousands of reasons behind the problem, but without a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) it's impossible to say more. – Some programmer dude Jun 01 '17 at 05:54
  • Yes, i have verified when the message arrives on the machine, via wireshark, that they are correct, i have checked byte by byte myself to make sure what i sent from the simulator sender is correct, and i have printed the entire character array out, in hex form, from the `recvfrom` function, to make sure it is correct as well, and this is when i noticed that my `00 00` were skipped/discarded. – Zac Jun 01 '17 at 06:11
  • You should look into how to mock a program and post it as a [mcve]. Chances are, you will have found the problem while doing this – Passer By Jun 01 '17 at 06:54

1 Answers1

0

The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.

I did not understand what this means at first, till i re-read over and over again, i realize that my hardware version is using a long of 4 bytes, rather than i should be using a short of 2 bytes instead, another question comes to mind, which is why is the bitfield limitation not working, or i may have understand it wrongly.

So after changing it from long to short, and with #pragma pack(1), the cast works fine now.

And how i found out was by using offsetof function to check

cout << offsetof (message_header, msg_num) << endl;
cout << offsetof (message_header, msg_len) << endl;
cout << offsetof (message_header, hardware_version) << endl;
cout << offsetof (message_header, sender_location ) << endl;
cout << offsetof (message_header, message) << endl;

And the printout is, then i realize the bitfield was not working at all.
0
4
8
12
16

After changing hardware_version, from long to short, AND without #pragma pack(1), the printout is still similar to the one above, however, once #pragma pack(1) is enabled, the printout is

0
4
6
10
14

Zac
  • 167
  • 1
  • 2
  • 7