Size of type WITHOUT alignment padding

#1

I’m writing some code which allocates a series of items into a contiguous region of memory, all of different types and sizes, something like: [val1: u32, val2: u8, etc].

Currently, the code looks something like this pseduocode:

block: *mut u8;
offset: isize;

for some_type in my_types {
    offset = round_up_to(offset, std::mem::align_of<some_type>());
    obj_ptr = block.offset(offset);

    // pointless padding space here!!!
    offset + std::mem::size_of::<some_type>();
}

My issue is that size_of::() not only returns the size of the type, but also padding to properly align what would be another of the same type afterwards in memory. I don’t want to do that - I already manage the alignment myself, and don’t want to waste space on pointless padding. For example, If I have a struct which requires 4 bytes of padding, followed by a struct which only requires 4 bytes of alignment, I want to start the next struct immediately instead of having 4 bytes of padding.

Unfortunately, code like:

#[attribute(packed)]
struct get_raw_size_of<T> {
    single_elem: T,
}

does not work, as the padding of single_elem is included anyways in the packed struct. Packing the original structs is also out of the question for me.

Is there a way to do this in stable rust?

0 Likes

#2

If you don’t pack the original, then any writes to that struct may also clobber the padding area. I suspect that your intended use of that padding would be Undefined Behavior.

2 Likes

#3

Looking at the compiler, it appears that this information is not exposed from the compiler.

@cuviper you’re probably correct, the compiler may well write to this padding for any purpose if it deems it an optimization (using a 16-byte write over a series of smaller ones), which is unfortunate. This isn’t currently done, but I can’t find anything about whether it’s allowed.

A representation without padding at the end would be difficult for a whole slew of reasons, but it would be useful to access that information and tell the compiler not to use that padding.

0 Likes

#4

It actually coalesces writes into one if you add one more field! Perhaps the cost of unaligned store is greater than cost of two writes, but smaller than three.

2 Likes

#5

This seems roughly the same as what https://github.com/rust-lang/rfcs/issues/1397 wants/proposes.

1 Like