How can I reset only class fill bytes?

I want to set class padding bytes to 0, since I save / load / compare / hash instances at the byte level, and initialized padding with garbage introduces non-determinism in each of these operations.

I know that this will achieve what I want (for trivially copied types):

struct Example { Example(char a_, int b_) { memset(this, 0, sizeof(*this)); a = a_; b = b_; } char a; int b; }; 

I don’t like to do this for two reasons: I like the constructor initiator lists, and I know that setting bits to 0 does not always coincide with zero initialization (for example, pointers and floats do not necessarily have zero values, all 0 bits).

As an aside, it is clearly limited to the type that can be copied trivially, but this is not a problem for me, since the operations listed above (loading / saving / comparing / hashing at the byte level), in any case, require trivially copied types.

What I would like is something like this [magic] snippet:

 struct Example { Example(char a_, int b_) : a(a_), b(b_) { // Leaves all members alone, and sets all padding bytes to 0. memset_only_padding_bytes(this, 0); } char a; int b; }; 

I doubt that such a thing is possible, therefore, if someone can offer a non-ugly alternative ... I'm all ears :)

+9
c ++ padding
source share
3 answers

I do not know how to do this automatically in pure C ++. To do this, we use our own code generation system (among other things). You could do this with a macro to which you loaded all of your member's variable names; it just looks for holes between offsetof (memberA) + sizeof (memberA) and offsetof (memberB).

Alternatively, serialize / hash by membership rather than as a binary blob. These are ten types of cleaners.

Oh, one more option - you can provide operator new , which explicitly cleared the memory before returning it. I am not a fan of this approach, though ..... it does not work for stack distribution.

+7
source share

You should not use padded structures in binary writing / reading. Just because padding can vary from one platform to another, which will lead to binary incompatibility.

Use some compiler options, such as #pragma pack (push, 1) , to disable padding when defining these writable structures and restore it using #pragma pack(pop) .

This, unfortunately, means that you are losing the optimization it provides. If this is a problem by carefully designing your structures, you can manually “stuff” them by inserting dummy variables. Then zero initialization becomes obvious, you just assign zeros to these dummies. I do not recommend this “manual” approach because it is very error prone, but since you are using the blob binary, you are probably already worried. But, by all means, unfastened structures were compared before.

+3
source share

I ran into a similar problem - and just saying that this is a poor design decision (according to dasblinkenlight comments) does not necessarily help, since you cannot control the hash code (in my case, I used an external library).

One solution is to create a custom iterator for your class that iterates through data bytes and skips the indent. Then you modify your hash algorithm to use your custom iterator instead of a pointer. One easy way to do this is to plan the pointer template so that it can accept an iterator - since the semantics of the pointer and the iterator are the same, you do not need to change any code outside templatizing.

EDIT : Boost provides a nice library that makes it easy to add custom iterators to your container: Boost.Iterator .

Whichever solution you choose, it is very preferable to avoid strip hashing, as this means that your hashing algorithm is closely related to your data structure. If you switch data structures (or, as Agent_L mentions, use the same data structure on a different platform, which is positioned differently), then it will create different hashes. On the other hand, if you only use the hash of the actual data, then you will always get the same hash value no matter which data structure you use later.

+2
source share

All Articles