rust, mem alloc/free

rust, mem alloc/free

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

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

Vec<>

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!

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

Box<>

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

Rc<>

    {
        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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章