rust, mem alloc/free
- String
- Vec<>
- vec!
- Box<>
- Rc<>
String
In rust, &str is a reference to a static string which can not be altered. Instead, it could be converted to a String by to_string(), which will eventaully allocate memory from heap:
&str.to_string -> &str.as_bytes.to_owned -> &[u8].to_vec -> Vec::with_capacity -> Global::alloc
In the end, String { vec: bytes } will be returned. Therefore, String is actually a Vec<>.
1 | let s = "def".to_string(); |
Call stack:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <alloc::alloc::Global as core::alloc::AllocRef>::alloc alloc.rs:169 alloc::raw_vec::RawVec<T,A>::allocate_in raw_vec.rs:87 alloc::raw_vec::RawVec<T>::with_capacity raw_vec.rs:141 alloc::vec::Vec<T>::with_capacity vec.rs:357 alloc::slice::hack::to_vec slice.rs:158 alloc::slice::<impl [T]>::to_vec slice.rs:394 alloc::slice::<impl alloc::borrow::ToOwned for [T]>::to_owned slice.rs:727 alloc::str::<impl alloc::borrow::ToOwned for str>::to_owned str.rs:205 <alloc::string::String as core::convert::From<&str>>::from string.rs:2224 <str as alloc::string::ToString>::to_string string.rs:2176 grep::main main.rs:83 std::rt::lang_start::{{closure}} rt.rs:67 std::rt::lang_start_internal::{{closure}} rt.rs:52 std::panicking::try::do_call panicking.rs:303 __rust_maybe_catch_panic lib.rs:86 std::panicking::try panicking.rs:281 std::panic::catch_unwind panic.rs:394 std::rt::lang_start_internal rt.rs:51 std::rt::lang_start rt.rs:67 main 0x000000000040814c __tmainCRTStartup 0x00000000004013c7 mainCRTStartup 0x00000000004014fb |
Vec<>
1 2 3 4 5 6 7 8 9 | pub struct Vec<T> { buf: RawVec<T>, len: usize, } { let mut s = Vec::new(); s.push(12); } |
Vec::new() only creates the Vec<> with len=0. THe floowing push() will check if there is room or it will allocate from heap.
1 2 3 4 5 6 | <alloc::alloc::Global as core::alloc::AllocRef>::alloc alloc.rs:169 alloc::raw_vec::RawVec<T,A>::reserve_internal raw_vec.rs:665 alloc::raw_vec::RawVec<T,A>::reserve raw_vec.rs:487 alloc::vec::Vec<T>::reserve vec.rs:499 alloc::vec::Vec<T>::push vec.rs:1172 grep::main main.rs:84 |
Free call stack:
1 2 3 4 5 6 | <alloc::alloc::Global as core::alloc::AllocRef>::dealloc alloc.rs:178 alloc::raw_vec::RawVec<T,A>::dealloc_buffer raw_vec.rs:713 <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop raw_vec.rs:723 core::ptr::drop_in_place mod.rs:177 core::ptr::drop_in_place mod.rs:177 grep::main main.rs:87 |
vec!
vec! will invoke into_vec and use ‘box’ to allocate the memory from heap.
1 2 3 4 5 6 7 8 9 | macro_rules! vec { ($elem:expr; $n:expr) => ( $crate::vec::from_elem($elem, $n) ); ($($x:expr),*) => ( <[_]>::into_vec(box [$($x),*]) ); ($($x:expr,)*) => ($crate::vec![$($x),*]) } |
Alloc/Push call stack:
1 2 3 | alloc::slice::hack::into_vec slice.rs:149 alloc::slice::<impl [T]>::into_vec slice.rs:415 grep::main main.rs:83 |
Free call stack:
1 2 3 4 5 6 | <alloc::alloc::Global as core::alloc::AllocRef>::dealloc alloc.rs:178 alloc::raw_vec::RawVec<T,A>::dealloc_buffer raw_vec.rs:713 <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop raw_vec.rs:723 core::ptr::drop_in_place mod.rs:177 core::ptr::drop_in_place mod.rs:177 grep::main main.rs:87 |
Box<>
It uses ‘box’ to allocate from heap.
1 2 3 4 5 6 7 | { let bb = Box::new("abc"); } pub fn new(x: T) -> Box<T> { box x } |
‘box’ is complied as exchange_malloc:
1 2 3 | alloc::alloc::exchange_malloc alloc.rs:221 alloc::boxed::Box<T>::new boxed.rs:175 grep::main main.rs:83 |
Free: box_free is used to free the memory.
1 2 3 | alloc::alloc::box_free alloc.rs:240 core::ptr::drop_in_place mod.rs:177 grep::main main.rs:84 |
Rc<>
1 2 3 | { let r = Rc::new(100); } |
Internally Rc is using RcBox for holding the value. RcBox is made by ‘box’ then.
Call stack:
1 2 3 | alloc::alloc::exchange_malloc alloc.rs:221 alloc::rc::Rc<T>::new rc.rs:323 grep::main main.rs:86 |
Free call stack: deallocate the RcBox…
1 2 3 4 5 | <alloc::alloc::Global as core::alloc::AllocRef>::dealloc alloc.rs:178 <alloc::rc::Rc<T> as core::ops::drop::Drop>::drop rc.rs:1119 core::ptr::drop_in_place mod.rs:177 core::mem::drop mod.rs:749 grep::main main.rs:88 |