В C/C++ и других низкоуровневых языках разработчик должен явно управлять размещением данных в памяти: на стеке (автоматические переменные) или в куче (выделение через malloc/new). В этих языках часто возникают ошибки с утечкой памяти, двойным освобождением либо использованием неинициализированной или уже удалённой памяти. Rust берёт на себя задачу строгого контроля памяти с помощью системы владения, без использования сборщика мусора.
Автоматическое управление памятью через стек удобно, но ограничено размерами (глубиной стека). Выделение в куче требует явного управления ресурсами, что опасно: можно забыть освободить память или нарушить области жизни указателей. Сборщик мусора — не всегда выход (затраты ресурсов, непредсказуемые паузы). Ошибки управления памятью приводят к авариям и уязвимостям.
В Rust стек и куча различаются автоматическим управлением: все значения по умолчанию размещаются на стеке, а для динамически размерных или долгоживущих объектов используется куча через умные указатели (например, Box<T>, Vec<T>). Система владения и заимствований гарантирует, что после передачи владения или завершения области жизни ресурсы будут освобождены автоматически. Всё это обеспечивает гарантированную безопасность на этапе компиляции и отсутствие излишних пауз от сборщика мусора.
Пример кода:
fn main() { let a = 42; // stack allocation let b = Box::new(42); // heap allocation let mut v = Vec::new(); v.push(1); v.push(2); // данные массива в heap }
Ключевые особенности:
Можно ли вручную освободить (drop) память на стеке?
Нет. Освобождение stack-allocated переменных происходит автоматически при выходе из области видимости, вручную делать drop бесполезно и даже недопустимо для stack pointers.
Вызывает ли перемещаемый (move) перенос на heap?
Нет. Перемещение переменной между владельцами не обязательно переносит её в heap, меняется только владение.
Гарантирует ли использование Box<T>, что T всегда в heap?
Да, Box<T> действительно выделяет T на куче, однако владение и область жизни всё так же строго контролируются.
В проекте используют глобальные vector'ы (Vec<T>) с ручной реализацией очистки через mem::forget или drop, иногда оставляя висячие указатели на удалённую память.
Плюсы:
Минусы:
Объекты явно размещаются через Box, передача данных происходит по правилу владения, для коллекций используют умные указатели и не возвращают ссылки на stack-переменные.
Плюсы:
Минусы: