Who Owns the Memory? Part 3: How Big Is your Type?
32 points by lukefleed
32 points by lukefleed
Great stuff once again:-)
Regarding repr(C):
each struct begins with a discriminant of the platform’s C int size: … tag: u64 …
Is the tag is supposed to be an int-sized discriminant? I expected i32 or c_int.
Is MyVariantB supposed to be the same layout as B(f32, u64)?
int compare_ints(const void *a, const void *b) { return *(const int*)a - *(const int*)b; }
This has an overflow bug :-)
Thanks! Right on both counts, u64 should be the platform's C int (typically i32), and MyVariantB doesn't match the variant definition. Fixing.
This has an overflow bug :-)
Just for the sake of completeness, there's the generic (when you can't promote to a wider arithmetic type) overflow-free and still branch-free alternative of (x >= y) - (x <= y) which also has the benefit of producing a canonical -1/0/+1 result. With SIMD-style cmp masks (where -1 represents true) you would flip the ordering: cmp_le(x, y) - cmp_le(y, x).
Although depending on what the caller does with the result of the ternary-valued comparison (e.g. comparison-based integer sorting), tricks like these can easily result in overall worse machine code quality versus something more transparent to the optimizing compiler like a < b ? -1 : a > b ? +1 : 0.
Classic overflow bug, you're right. I use the safe pattern in compare_by_distance below, but it should be consistent. Will fix.
Very nice read!
Visualizing Layouts#
Gcc and clang have -Wpadded to warn on missing padding fields.
Polymorphism: Monomorphization vs Vtables
There is no std::variant/tagged enum as very common dispatch method. I dont see reasons other than ABI to not use std::variant over virtual dispatch in C++. In C one can easily hand-roll the equivalent.
Pointer tagging is an alternative, but that does generally not work well with compiler inlining due to missing standardization and not at all for hardware branch predictors (due to arbitrary bit pattern relations not detectable in hardware).
Good points. And yes, std::variant + std::visit is C++'s equivalent of the enum dispatch pattern, should have mentioned it alongside the Rust example. Thanks!
We can examine the actual representation using
std::ptr::metadata:
I don't see any use of std::ptr::metadata in the following code block. Another typo?
The tracking issue rust-lang/rust#68262 has seen little progress.
Was not hyperlinking rust-lang/rust#68262 an active decision?