README.md 2.9 KB

ralloc

Redox's fast & memory efficient userspace allocator.

A note on its state.

It fully works, although it is relatively slow, since it haven't been optimized yet. There is currently no known bugs, but it haven't been carefully reviewed yet, so avoid using it in security critical programs.

I consider the state of the code quality very good.

Using ralloc

Add ralloc to Cargo.toml:

[dependencies.ralloc]
git = "https://github.com/redox-os/ralloc.git"

then import it in your main file:

extern crate ralloc;

ralloc is now ready to roll!

Note that ralloc cannot coexist with another allocator, unless they're deliberately compatible.

Features

Custom out-of-memory handlers

You can set custom OOM handlers, by:

extern crate ralloc;
use fail::set_oom_handler;

fn my_handler() -> ! {
    println!("Oh no. Blame somebody.");
}

fn main() {
    set_oom_handler(my_handler);
    // Do some stuff...
}

Debug check: double free

Ooh, this one is a cool one. ralloc detects various memory bugs when compiled with debug_assertions. These checks include double free checks:

fn main() {
    // We start by allocating some stuff.
    let a = Box::new(500u32);
    // Then we memcpy the pointer (this is UB).
    let b = Box::from_raw(&a as *mut u32);
    // Now both destructors are called. First a, then b, which is a double
    // free. Luckily, ralloc provides a nice message for you, when in debug
    // mode:
    //    Assertion failed: Double free.

    // Setting RUST_BACKTRACE allows you to get a stack backtrace, so that you
    // can find where the double free occurs.
}

Partial deallocation

Many allocators limits deallocations to be allocated block, that is, you cannot perform arithmetics or split it. ralloc does not have such a limitation:

use std::mem;
fn main() {
    // We allocate 200 bytes.
    let vec = vec![0u8; 200];
    // Cast it to a pointer.
    let ptr = vec.as_mut_ptr();

    // To avoid UB, we leak the vector.
    mem::forget(vec);

    // Now, we create two vectors, each being 100 bytes long, effectively
    // splitting the original vector in half.
    let a = Vec::from_raw_parts(ptr, 100, 100);
    let b = Vec::from_raw_parts(ptr.offset(100), 100, 100);

    // Now, the destructor of a and b is called... Without a segfault!
}

Seperate deallocation

Another cool feature is that you can deallocate things that weren't even allocated buffers in the first place!

Consider that you got a unused static variable, that you want to put into the allocation pool:

extern crate ralloc;

static mut BUFFER: [u8; 256] = [2; 256];

fn main() {
    // Throw `BUFFER` into the memory pool.
    unsafe {
        ralloc::free(&mut BUFFER as *mut u8, 256);
    }

    // Do some allocation.
    assert_eq!(*Box::new(0xDEED), 0xDEED);
}

Thread local allocator

TODO

Safe SBRK

TODO

Lock reuse

TODO

Platform agnostic

TODO