semtexzv
semtexzv

Reputation: 139

Allocating a buffer on the heap at runtime

I am learning Rust by writing simple binary decoder.

I'm using a BufferedReader with the byteorder crate to read numbers, but I'm having problems with reading byte buffers.

I want to read byte data into buffer allocated at runtime. Then I want to pass ownership of this buffer to a struct. When struct is no longer in use, the buffer should be deallocated.

There seems to be no way to allocate array with size determined at runtime on heap except some Vec::with_capacity() hacks. Any ideas how to implement this with proper Rust semantics?

Upvotes: 4

Views: 8001

Answers (3)

Shepmaster
Shepmaster

Reputation: 432189

I tried using box but it seems that it is experimental and I can't use it with release branch. Any ideas how to implement this with proper Rust semantics?

This is covered in The Rust Programming Language, specifically the section "Using Box<T> to Point to Data on the Heap".

Use Box::new:

fn main() {
    let answer: Box<u8> = Box::new(42);
}

See also:

Upvotes: 0

Matthieu M.
Matthieu M.

Reputation: 300409

Rust is a low-level language; thus you can allocate raw memory and then fill it with objects yourself. Of course, it will require unsafe code, as all fiddling with raw memory does.

Here is a complete example:

use std::{
    alloc::{self, Layout},
    mem, ptr,
};

fn main() {
    unsafe {
        let layout = Layout::from_size_align(512 * 1024, 4 * 1024).expect("Invalid layout");
        let mut raw: *mut i32 = mem::transmute(alloc::alloc(layout));

        for i in 0..(512 * 1024 / 4) {
            ptr::write(raw, i as i32);
            raw = raw.offset(1)
        }
    }
}

Of course, in real code, I would just use Vec to safely manage the memory for me. It's just simpler!

Upvotes: 6

David
David

Reputation: 469

This will create a pre-allocated mutable 500MB byte buffer of zeros stored on the heap with no need for unsafe rust:

// Correct

let mut buffer = vec![0_u8; 536870912];

Note that the following code below is not a good idea and will most likely result in a stack overflow because the buffer is created on the stack before being boxed and moved to the heap.

// Incorrect - stack used

let mut bytes: Box<[u8]> = Box::new([0_u8; 536870912])

// Incorrect - slow

let mut bytes = Vec::with_capacity(536870912);
for _ in 0..bytes.capacity() {
    bytes.push(0_u8);
}

Upvotes: 12

Related Questions