Огляд пам'яті програми
Програми виділяють пам'ять двома способами:
-
Стек: безперервна область пам'яті для локальних змінних.
- Значення мають фіксовані розміри, відомі під час компіляції.
- Надзвичайно швидко: просто перемістіть вказівник стека.
- Легко керувати: слідує за викликами функцій.
- Чудова локальність пам'яті.
-
Купа: Зберігання значень поза викликами функцій.
- Значення мають динамічні розміри, визначені під час виконання.
- Трохи повільніше, ніж стек: потрібн певний облік.
- Немає гарантії локальності пам'яті.
Приклад
Створення String
поміщає метадані фіксованого розміру в стек, а дані динамічного розміру, фактичний рядок, у купу:
fn main() { let s1 = String::from("Привіт"); }
This slide should take about 5 minutes.
-
Нагадайте, що тип
String
підтримуєтьсяVec
, тому має ємність і довжину та може зростати, якщо мутабельна, через перерозподіл у купі. -
Якщо студенти запитають про це, ви можете нагадати, що основна пам’ять розподіляється за допомогою System Allocator і користувальницькі розподільники можуть бути реалізовано за допомогою Allocator API
Більше інформації для вивчення
Ми можемо перевірити розташування пам’яті за допомогою unsafe
Rust. Однак ви повинні зазначити, що це по праву небезпечно!
fn main() { let mut s1 = String::from("Привіт"); s1.push(' '); s1.push_str("світ"); // НЕ РОБІТЬ ЦЬОГО ВДОМА! Тільки в навчальних цілях. // String не надає жодних гарантій щодо своєї розмітки, тому це може призвести до // невизначеної поведінки. unsafe { let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1); println!("capacity = {capacity}, ptr = {ptr:#x}, len = {len}"); } }