How can I zero just the padding bytes of a class?

此生再无相见时 提交于 2019-12-05 02:46:35

There's no way I know of to do this fully automatically in pure C++. We use a custom code generation system to accomplish this (among other things). You could potentially accomplish this with a macro to which you fed all your member variable names; it would simply look for holes between offsetof(memberA)+sizeof(memberA) and offsetof(memberB).

Alternatively, serialize/hash on a memberwise basis, rather than as a binary blob. That's ten kinds of cleaner.

Oh, one other option -- you could provide an operator new which explicitly cleared the memory before returning it. I'm not a fan of that approach, though..... it doesn't work for stack allocation.

You should never use padded structs when binary writing/reading them. Simply because the padding can vary from one platform to another which will lead to binary incompatibility.

Use some compiler options, like #pragma pack (push, 1) to disable padding when defining those writable structs and restore it with #pragma pack(pop).

This sadly means you're losing the optimization provided by it. If that is a concern, by carefully designing your structs you can manually "pad" them by inserting dummy variables. Then zero-initialization becomes obvious, you just assign zeros to those dummies. I don't recommend that "manual" approach as it's very error-prone, but as you're using binary blob write you're probably concerned already. But by all means, benchmark unpadded structs before.

I faced a similar problem - and simply saying that this is a poor design decision (as per dasblinkenlight's comment) doesn't necessarily help as you may have no control over the hashing code (in my case I was using an external library).

One solution is to write a custom iterator for your class, which iterates through the bytes of the data and skips the padding. You then modify your hashing algorithm to use your custom iterator instead of a pointer. One simple way to do this is to templatize the pointer so that it can take an iterator - since the semantics of a pointer and an iterator are the same, you shouldn't have to modify any code beyond the templatizing.

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

Whichever solution you go for, it is highly preferable to avoid hashing the padding as doing so means that your hashing algorithm is highly coupled with your data structure. If you switch data structures (or as Agent_L mentions, use the same data structure on a different platform which pads differently), then it will produce different hashes. On the other hand, if you only hash the actual data itself, then you will always produce the same hash values no matter what data structure you use later.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!