0
votes

I need to create binary data packets in C code. However, I am missing some fundamental point. Currently, there are already structs defined and I will need to use them (at least for reading packet data). The same structure will be used both for received packets and for sent packets. Here are packet structs:

typedef struct {

  uint8_t packetType;
  uint16_t packetBody;

} MyStruct;

and another struct:

typedef union {

  const uint8_t *bytes; 
  MyStruct *packet;

} MyPacket;

Here's the function that should take a pointer to the struct, fill it with data and return back:

void packetWithBytes(MyPacket *packet)
{
  packet->packet->packetType = 1; // crashed with EXC_BAD_ACCESS
  packet->packet->packetBody = 3;
}

Here's a call to my function that should return a pointer to binary data:

MyPacket *packetRef;
packetWithBytes(packetRef); 

NSData *data = [NSData dataWithBytes:packetRef->bytes length:sizeof(packetRef->bytes)];

I feel I should allocate some space somewhere (with malloc) but not sure where and how to do that. The calling part code should not know any details about the size of the packet. Tried to do allocation but getting the same error:

void packetWithBytes(MyPacket *packet)
{
  packet->bytes = malloc(sizeof(uint8_t) + sizeof(uint16_t)); //crash
  packet->packet->packetType = 1;
  packet->packet->packetBody = 3;
}

Tried to remove const from MyStruct member bytes but getting the same error. I'm not not very familiar with C, so help would be very appreciated.

1
Note that this is inviting trouble. The rules for binary layout of struct members is at best platform dependent if not compiler specific. - Simon Richter
@SimonRichter Not to mention there are even no unions only structs. I feel there's a lot to learn yet for OP. - user529758
Listen to what Simon Richter is saying. If you need to do binary serialization consider something cross-compiler/cross-platform such as Google Protocol Buffers. - Joe

1 Answers

4
votes
MyPacket *packetRef;
packetWithBytes(packetRef);

is the problem. packetRef is an uninitialized pointer and such it may point to an invalid memory location - dereferencing it is undefined behavior. You can solve this in two way:

MyPacket *packetRef = malloc(sizeof(*packetRef));
packetWithBytes(packetRef);

or

MyPacket packetRef;
packetWithBytes(&packetRef);