2

I don't understand in Rust what is happening with a struct in a struct when we Box the parent struct.

struct Outer1 {
    child: Inner1,
}

struct Inner1 {
    n: i32,
}

struct Outer2 {
    child: Box<Inner2>,
}

struct Inner2 {
    n: Box<i32>,
}

pub fn main() {
    let x1 = Box::new(Outer1 {
        child: Inner1 { n: 1 },
    });
    let x2 = Box::new(Outer2 {
        child: Box::new(Inner2 { n: Box::new(1) }),
    });
}

x2.child and x2.child.n should be on the heap, right? Where is x1.child and x1.child.n: the stack or the heap?

If child.n would be of type String, n should be a reference and String needs no Box to be on the heap? Is this correct?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Markus
  • 512
  • 1
  • 4
  • 21

2 Answers2

7

Imagine each type (Outer1, Inner1, i32) has a color and that memory slots are made up of one or more stacked/embedded colored frames of bytes.

struct Outer1 {
    child: Inner1,
}

struct Inner1 {
    n: i32,
}

let x1 = Box::new(Outer1 {
    child: Inner1 { n: 1 },
});

has this layout:

enter image description here

struct Outer2 {
    child: Box<Inner2>,
}

struct Inner2 {
    n: Box<i32>,
}

let x2 = Box::new(Outer2 {
    child: Box::new(Inner2 { n: Box::new(1) }),
});

has this layout:

enter image description here

Each Box<Something> start a new colored frame.

Obviously memory is not colored: it is a concept that may help in representation: what really exists are only bytes, and eventually some waste of space due to memory alignments.

Below the memory layout for a struct containig a String property.

enter image description here

A String is made up of three components: a pointer to a buffer, lenght and capacity (in the example they are on the stack) and a buffer that is always stored on the heap.

Note: it the examples above pointers size are relative to 64 bit architecture.

attdona
  • 17,196
  • 7
  • 49
  • 60
3

Do I need to Box child structs of a Boxed struct to get everything on the heap?

No. When you box a value, you box the entire value, which means all of the member values. Since every member of that value is inside the box, everything is on the heap.

What happens if I do inner boxing? Does it point to different memory?

Yes. The variable on the stack will point to data in the heap which will then point at different data on the heap.

+-----------+         +----------+
|   Stack   |         |   Heap   |
+-----------+         +----------+
|           +--------->          +------+
|           |         |          |      |
|           |         |          |      |
|           |         |          |      |
+-----------+         |          |      |
|   .....   |         +----------+      |
+-----------+         |   ....   |      |
|           |         +----------+      |
|           |         |          |      |
|           |         |          <------+
|           |         |          |
|           |         |          |
|           |         |          |
|           |         |          |
|           |         |          |
+-----------+         +----------+
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • What happen's if I do inner boxing? Does it point to different memory? Or is it removed by compiler? – Markus Oct 22 '18 at 21:32
  • 2
    @Markys Everytime you create a box, a new memory segment on the heap is allocated, so the inner box points to different memory. Creating a box is about more than whether something is stored on the heap of the stack, so the compiler can't simply decide to store something inline that you request to be stored in a box, at least not in the general case, since the behaviour is observably different. – Sven Marnach Oct 22 '18 at 22:52