Understanding the memory layout of Rc<T> pointers

Hello,

I would like to understand the memory layout while executing the following piece of code, taken from the standard library example (Cloning references)

use std::rc::Rc;

let vec_var = vec![1.0, 2.0, 3.0];
let foo = Rc::new(vec_var);
let a = Rc::clone(&foo);
let b = Rc::clone(&foo);

I have imagined the memory layout like the following drawing. Is that correct?
Thank you!

Not correct. There is a single count for the Vec object. Move count and weak to the heap, stored just before the (pointer, len, cap) triple.

5 Likes

Note that you don't have to guess or make any assumptions. The source code of the Rust standard library is freely available right from the official documentation site, so you can just read it.

It shows:

struct RcBox<T: ?Sized> {
    strong: Cell<usize>,
    weak: Cell<usize>,
    value: T,
}

...

pub struct Rc<T: ?Sized> {
    ptr: NonNull<RcBox<T>>,
    phantom: PhantomData<RcBox<T>>,
}

I.e., Rc is really just a pointer, and the value lives together with the two reference counts.

4 Likes

So, the correct memory layout drawing should be the following:

Hello and thanks a lot for your help, you've really thrown light on it.

So, continuing my thoughts in the above discussion the following drawing should depict the memory layout of the following code take from the Book (Listing 15-18: A definition of List that uses Rc)

enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use crate::List::{Cons, Nil};
use std::rc::Rc;

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    let b = Cons(3, Rc::clone(&a));
    let c = Cons(4, Rc::clone(&a));
}

The exact order of the ptr, len, cap fields of a vector could be different than what you used (the order is not guaranteed and may change from one compile to another). But otherwise yes.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.