Why does Box<[u8]> occupy 16B?


#1

I see that Box is actually a tuple struct that encapsulates Unique.

From https://doc.rust-lang.org/src/core/ptr.rs.html#2336-2344 I see that Unique is essentially NonZero<*const T>.

From https://doc.rust-lang.org/src/core/nonzero.rs.html#65 I see that Nonzero is again a tuple struct that only contains T.

In summary, a Box is merely a pointer, from the view of space.

I’m using a 64-bit machine, so the raw pointer will occupy 8B.

println!("{:?}", mem::size_of::<Box<[u8]>>());

gives me 16 instead of 8.

What’s wrong?


#2

The magic of Dynamically Sized Types: https://doc.rust-lang.org/beta/nomicon/exotic-sizes.html

TLDR: It’s a ‘fat pointer’ that includes an actual pointer plus the array’s length.


#3

Strange, if I run the following code on the Rust Playground,

use std::mem;
fn main() {
    println!("size of pointer is {:?}", mem::size_of::<*const u8>());
   println!("size of box is {:?}", mem::size_of::<Box<[u8; 10_000]>>());
}

I get

size of pointer is 8
size of box is 8

I’m printing the size of the pointer to show it’s a 64bit platform. What’s the difference between your example and mine?

Joeri


#4

A [u8; 10_000] array has a statically known size in the type, so we don’t need to store the length anywhere. A [u8] has a dynamic length, so that’s stored with the box pointer.