Skip to content

String::try_reserve

String methods · Strings

Level: reference · for working programmers

One line: reserve that returns Result instead of aborting the process when the allocation cannot be made.

pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>

Stable since 1.57.0.

Rust's default on allocation failure is to abort — no unwinding, no Result, no chance to recover. For most programs that is the right call. It is the wrong call when the requested size comes from input: a length field in a protocol, a Content-Length header, a record count in a file. A hostile or corrupt value then turns into a process kill.

try_reserve gives you the failure as a value. TryReserveError distinguishes two kinds: CapacityOverflow, where the arithmetic itself is impossible, and AllocError, where the allocator refused.

Note it can only protect the allocation it performs. A subsequent push_str that grows past the reserved capacity aborts as usual, so the pattern is: reserve what the input claims, handle the error, then write no more than that.

Example

string_try_reserve.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let mut s = String::from("hi");

    // The ordinary case succeeds and behaves like reserve.
    println!("{:?}", s.try_reserve(100).is_ok());
    println!("capacity {}", s.capacity());

    // An impossible request is an error, not an abort.
    let mut t = String::new();
    match t.try_reserve(usize::MAX) {
        Ok(()) => println!("reserved"),
        Err(e) => println!("refused: {e}"),
    }

    // The pattern: trust the length only as far as the allocator agrees.
    fn read_claimed(claimed: usize) -> Result<String, String> {
        let mut buf = String::new();
        buf.try_reserve(claimed).map_err(|e| format!("cannot hold {claimed}: {e}"))?;
        buf.push_str("payload");
        Ok(buf)
    }
    println!("{:?}", read_claimed(16));
    println!("{:?}", read_claimed(usize::MAX).is_err());
}

Verified output of string_try_reserve.rs — regenerated by tools/run_examples.py, never hand-typed.

true
capacity 102
refused: memory allocation failed because the computed capacity exceeded the collection's maximum
Ok("payload")
true

See also

String::try_reserve in the standard library ↗

Po polsku

Domyślną reakcją Rusta na brak pamięci jest abort — bez odwijania stosu, bez Result, bez szansy na reakcję. W większości programów to rozsądny wybór, ale zamienia się w lukę bezpieczeństwa, gdy rozmiar pochodzi z danych wejściowych: pole długości w protokole, nagłówek Content-Length, liczba rekordów w pliku — wtedy jedna złośliwa liczba wystarczy, żeby ubić proces. try_reserve oddaje tę porażkę jako wartość, a TryReserveError rozróżnia dwa przypadki: CapacityOverflow, gdy niemożliwa jest sama arytmetyka (to właśnie komunikat z przykładu), i AllocError, gdy alokator odmówił. Warto pilnować zasięgu tej ochrony: zabezpieczona jest wyłącznie ta jedna alokacja, więc późniejszy push_str wykraczający poza zarezerwowaną pojemność przerwie proces jak zwykle — wzorzec brzmi „zarezerwuj tyle, ile deklaruje wejście, obsłuż błąd, a potem nie zapisuj więcej”.

Szukaj po polsku: obsługa braku pamięci · walidacja długości z danych wejściowych · rust try_reserve TryReserveError · rust allocation failure abort