Home > Back-end >  How to CRC check a whole structure (without padding)
How to CRC check a whole structure (without padding)

Time:06-25

I have a structure which contains memory for an EEPROM:

#pragma pack(push,1)
struct EEPROM_Memory
{
  char Device_ID[8];
  uint8_t Version_No;
  otherRandomVariables...
};
#pragma pack(pop)

I then create an instance, populate the struct and calculate it's CRC using:

CRC32::calculate(reinterpret_cast<uint8_t*>(&(memory)), sizeof(EEPROM_Memory));

I have been going crazy trying to figure out why the CRC check returns different values.

My best guess is pragma pack is not working therefore there is still some padding. This padding is volatile thus resulting in different CRC values.

What would be a nice solution (i.e not manually checking each value in the struct for their CRC)?

Any suggestions much appreciated!

P.S. I have looked at this question but sadly it does not give many suggestions on what to do. Surely this is a common problem!

P.P.S I am using an ESP32 microcontroller, unsure which compiler. The CRC library I am using is CRC32 by Christopher Baker.

CodePudding user response:

Pretty sure the pack is working as it should and you are using it wrong.

Note that pack is not recursive. So if your any of your otherRandomVariables is a struct then that struct may contain padding.

What you should do is static_assert the size of the struct. Then you know if it has the expected size or some padding. If it contains any structs assert the size of those structs first.

CodePudding user response:

I have a suspicion that memory is a pointer, and you're taking its address, thereby calculating the checksum of the pointer and following bytes rather than the data it points to.

The reinterpret_cast is wholly unnecessary, the calculate function you are using is templated. And like all the cast keywords, reinterpret_cast cripples compiler type-checking and disables a whole lot of useful warnings and errors, so you really should consider it a last resort.

Try this:

auto result = CRC32::calculate(memory, 1);

If and only if you have tried that and it fails to compile because memory is not actually a pointer, then

auto result = CRC32::calculate(&memory, 1);
  • Related