String::leak¶
Level: reference · for working programmers
One line: Consumes the String and returns a &'static mut str — the memory is never freed, and that is the point.
Stable since 1.72.0.
It gives up ownership to nobody. The allocation lives until the process exits, which is what buys the 'static lifetime: the reference is valid forever because nothing will ever invalidate it.
That is a legitimate trade for values that live as long as the program anyway — a configuration string read at startup and referenced everywhere, or a name that has to satisfy a 'static bound in a library API. It is a bug when it happens per request or per iteration, where it is simply an unbounded memory leak.
The reference is &'static mut str, so it is unique and mutable; it can be reborrowed as &'static str.
Box::leak(s.into_boxed_str()) is the older spelling of the same thing. Neither can be undone — there is no un-leak, short of reconstructing through from_raw_parts with the exact capacity, which leak has already discarded.
Example¶
string_leak.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let built = format!("config-{}", 42);
let forever: &'static str = String::leak(built);
println!("{forever:?}");
// 'static, so it satisfies a bound that a borrowed String could not.
fn needs_static(s: &'static str) -> usize { s.len() }
println!("{}", needs_static(forever));
// The reference is mutable before you narrow it.
let mut_ref: &'static mut str = String::from("hello").leak();
mut_ref.make_ascii_uppercase();
println!("{mut_ref:?}");
// The older spelling.
let boxed: &'static str = Box::leak(String::from("also static").into_boxed_str());
println!("{boxed:?}");
// The bug shape: leaking per iteration is an unbounded leak.
let leaked_total: usize = (0..3).map(|i| String::leak(format!("item{i}")).len()).sum();
println!("{leaked_total} bytes leaked deliberately");
}
Verified output of string_leak.rs — regenerated by tools/run_examples.py, never hand-typed.
See also¶
String::into_boxed_str— handing off ownership that still gets freedString::into_raw_parts— the same abdication, with the pieces to undo itstr::into_string— the trip back fromBox<str>String::from_raw_parts— the only route back, if you kept the capacity
String::leak in the standard library ↗
Po polsku¶
Nazwa jest dosłowna i celowo prowokacyjna: leak to wyciek pamięci popełniony umyślnie. Metoda pochłania łańcuch znaków i zwraca &'static mut str — bufor nie zostanie zwolniony aż do zakończenia procesu, i właśnie stąd bierze się statyczny czas życia (static lifetime): referencja jest ważna zawsze, bo nic nigdy jej nie unieważni. To uczciwy interes dla danych, które i tak żyją tyle co program — konfiguracja wczytana przy starcie, nazwa, którą trzeba wcisnąć w API żądające 'static — i zwyczajny błąd tam, gdzie powtarza się raz na żądanie albo raz na obrót pętli; ostatnia linijka przykładu wycieka 15 bajtów w trzech obrotach i nic tego nie posprząta. Odwrotu nie ma, bo leak wyrzuca pojemność, więc nawet from_raw_parts już nie uratuje sytuacji — gdy chcesz zachować możliwość oddania pamięci, sięgnij po into_raw_parts, które wszystkie trzy liczby zwraca.
Szukaj po polsku: celowy wyciek pamięci · statyczny czas życia · rust String leak · rust Box::leak static str · rust static lifetime bound