Rust memory allocation questions

I am trying to understand rust's memory allocation working.
I am experimenting with creating a vec on a small linux VM.
I am trying:

let size_as_u8: usize = (size_definition*1024*1024).try_into().unwrap();
let mut hog = vec![0u8; size_as_u8];

This creates an allocation of size_as_u8 bytes, but does not page in any memory (except for one page)).

VM total memory is 2G, swap is 2G.

If I set size_definition to 3000 (approx 3G) this succeeds.
If I set size_definition to 4000, this results in:

memory allocation of 4194304000 bytes failed
Aborted (core dumped)

The memory allocation failing is consistent with linux memory limits (allocating more than available memory and swap should fail), overcommit_memory is set to 0.

What I am trying to figure out is if rust did stop this allocation itself without the OS telling it, or if it did allocate the memory, gotten ENOMEM, and as a result of that abort the execution.
If it did get ENOMEM, how can I catch ENOMEM (in gdb), and where is the code that handles this?

If Rust stops the allocation itself when creating a Vec, then this function runs:

// from alloc/raw_vec.rs

fn capacity_overflow() -> ! {
    panic!("capacity overflow");
}

If you didn't see it print "capacity overflow", then the error came from the OS.

2 Likes

You are right. I realised I could verify my own hypothesis by setting overcommit on linux to always overcommit (echo 1 > /proc/sys/vm/overcommit_memory), and then the allocation succeeds.

If I enable cores being written and look at the backtrace of the core file, I see rust calling abort because it got the ENOMEM signal, and it seems to be the rust convention to abort if it did run out of memory. But I would like to find the part of rust that captures the ENOMEM from the OS.

Rust calls std::alloc::alloc, which returns a null pointer if the allocation fails. When that happens, the Vec calls std::alloc::handle_alloc_error, which will abort the program.

The std::alloc::alloc method just calls malloc from libc by default, so the ENOMEM is probably converted into returning a null pointer inside libc.

3 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.