Initializing structures on heap

Is there a way to initialize a buffer on the heap without first initializing it on the stack and then moving it on to the heap?

pub struct Agent {
    name: String,
    designation: String,
    age: u8
}

pub fn stalloc() {
    let s = Agent {
        name: "frank".into(),
        designation: "006".into(),
        age: 37
    };

    let h = Box::new(s);
}

It would be nice if Rust has special plumbing to realize that the stack object isn't actually needed, so it could move the initialization into Box::new() and perform it just after the allocation. I realize this isn't feasible, but is there some other mechanism through which it is possible? Out of historical curiosity -- could Rust's old box keyword do this?

You probably can do this if you use unsafe, but otherwise no. And yes, the box keyword did do this.

1 Like

It was part of what box was supposed to do. Placement was unaccepted in part because it didn't actually work reliably.

2 Likes

The way on nightly looks like it's Box::new_uninit, though that will very much take unsafe code to do.

That said, note that in your example LLVM does build the Agent right on the heap: no allocas in https://rust.godbolt.org/z/W3jzWGxff

        call    qword ptr [rip + __rust_alloc@GOTPCREL]
        test    rax, rax
        je      .LBB0_6
        mov     qword ptr [rax], r14
        mov     qword ptr [rax + 8], 5
        mov     qword ptr [rax + 16], 5
        mov     qword ptr [rax + 24], rbx
        mov     qword ptr [rax + 32], 3
        mov     qword ptr [rax + 40], 3
        mov     byte ptr [rax + 48], 37

rather than building it on the stack then memcpy'ing it over to the heap, albeit it tries to allocate the strings before the box.

The manual way, with the box allocation first, is

pub fn stalloc() -> Box<Agent> {
    let mut b = Box::<Agent>::new_uninit();
    let s = Agent {
        name: "frank".into(),
        designation: "006".into(),
        age: 37
    };
    b.write(s);
    unsafe { b.assume_init() }
}

Tracking issue: Tracking issue for uninitialized constructors for Box, Rc, Arc · Issue #63291 · rust-lang/rust · GitHub

2 Likes

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.