@greenmoonmoon that wouldn't be the level at which i would counteract it, as it's quite fragile to maintain.
better would be to explicitly memclear a buffer then init the fields in it - before passing the key to any hashmap function. at least that's my plan when i encounter this again.
@greenmoonmoon personally i think it's crazy¹ not to clear memory on allocation. speedfreaks cut too many corners.
¹ inviting trouble
@dotstdy @floooh @lritter @greenmoonmoon There is the GCC extension __builtin_clear_padding: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fclear_005fpadding
But as soon as you move or modify the objects, the padding bits may change again. So hash it immediately after clearing the padding bits.
Unfortunately, GCC is the only compiler that has it AFAIK.
@foonathan @dotstdy @lritter @greenmoonmoon hmm interesting... apparently MSVC has a similar `__builtin_zero_non_value_bits`.
LLVM seems to be missing something similar so far though (https://github.com/llvm/llvm-project/issues/64830)... seems to be in progress though:
https://github.com/llvm/llvm-project/actions/runs/19788158702

This is basically identical to #46030 ("Implement __builtin_zero_non_value_bits which was recently added to MSVC") except for GCC instead of MSVC. C++20 includes P0528R3 and P1123R0, which together...
@floooh @lritter @greenmoonmoon Yeah, surrounding the structs you want this on with:
#pragma pack(push, 1)
// structs
#pragma pack(pop)
That's right, right? Been a while since I learnt about that.
@pkhuong @floooh @miblo @greenmoonmoon these are not manually set up structs - they appear through the nudl codegen.
so i would have to ban unaligned table column configurations, and the only reason i could state for this is "because i am incompetent".
if i have no other course of action, i'll have to rewrite the relevant bits of stb_ds to use my macro type dispatch stuff. it's ok. just more work. 🫥
@lritter Let's say you have struct { int x; char y; double z; };
You'd have
```
enum
{
after_x = alignof(char) - (sizeof(int)) % alignof(char) % alignof(char),
after_y = (alignof(double) - (sizeof(int) + padding_after_x + sizeof(char)) % alignof(double)) % alignof(double),
...
}
```
and tail padding would use `alignof(union { one-of-every-type; })`.
and instead generate `struct {int x; char padding_after_x[after_x]; char y; char padding_after_y[after_y]; double z; char tail_padding[tail];}`.
@manx @lritter @greenmoonmoon it should be safe when each "regular" struct member is still properly aligned (e.g. when using packed structs with "manually defined" padding, like below).
(it gets interesting though when the GPU alignment rules differ from the C alignment rules)
> At that point, #pragma pack is kind of pointless, because it does nothing.
...the whole point of the thread is to make the content of padding bytes explicitly defined, and this is one way to do it (the other solution that came up is to use a compiler-specific builtin to zero the padding bytes, not yet supported by clang though)

struct foo { std::uint8_t x; std::uint32_t y; }; static_assert(!std::has_unique_object_representations<foo>::value); struct bar { std::uint8_t x; std::uint8_t padding1[3]; std::uint32_t y; }; static_assert(std::has_unique_object_representations<bar>::value);
@lritter It's not just Clang. Padding bytes are a 'no-go-area' for C and C++ compilers.
One area where I've seen padding bytes being lost was calling a function which takes a struct by value (and I seem to remember not just for small structs where the struct content is passed in registers), or even just assigning one struct to another without using memcpy (but tbh I wouldn't even trust memset or memcpy, since these are essentially builtins today).