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<>.
let s = "def".to_string();
Call stack:
<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
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.
<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:
<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! will invoke into_vec and use ‘box’ to allocate the memory from heap.
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:
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:
<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
It uses ‘box’ to allocate from heap.
{
let bb = Box::new("abc");
}
pub fn new(x: T) -> Box<T> {
box x
}
‘box’ is complied as exchange_malloc:
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.
alloc::alloc::box_free alloc.rs:240
core::ptr::drop_in_place mod.rs:177
grep::main main.rs:84
{
let r = Rc::new(100);
}
Internally Rc is using RcBox for holding the value. RcBox is made by ‘box’ then.
Call stack:
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…
<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