Основная идея управления ресурсами (включая память) в программе, независимо от стратегии, заключается в том, что ресурсы, связанные с недостижимыми «объектами», могут быть возвращены. Помимо памяти, этими ресурсами могут быть блокировки мьютексов, дескрипторы файлов, сокеты, соединения с базой данных ...
Языки со сборщиком мусора периодически сканируют память (так или иначе), чтобы найти неиспользуемые объекты, освободить связанные с ними ресурсы и, наконец, освободить память, используемую этими объектами.
В Rust нет сборщика мусора, как он справляется?
У Rust есть право собственности. Используя систему аффинных типов , он отслеживает, какая переменная все еще хранится в объекте, и, когда такая переменная выходит за пределы области видимости, вызывает его деструктор. Вы можете легко увидеть, как действует система аффинных типов:
fn main() {
let s: String = "Hello, World!".into();
let t = s;
println!("{}", s);
}
Урожайность:
<anon>:4:24: 4:25 error: use of moved value: `s` [E0382]
<anon>:4 println!("{}", s);
<anon>:3:13: 3:14 note: `s` moved here because it has type `collections::string::String`, which is moved by default
<anon>:3 let t = s;
^
что прекрасно иллюстрирует, что в любой момент времени, на уровне языка, право собственности отслеживается.
Это владение работает рекурсивно: если у вас есть Vec<String>
(то есть динамический массив строк), то каждая String
принадлежит тому, Vec
который сам принадлежит переменной или другому объекту и т. Д., Таким образом, когда переменная выходит за пределы области видимости, он рекурсивно освобождает все ресурсы, которые он удерживал, даже косвенно. В случае с Vec<String>
этим означает:
- Освобождение буфера памяти, связанного с каждым
String
- Освобождение буфера памяти, связанного с
Vec
самим собой
Таким образом, благодаря отслеживанию владения время жизни ВСЕХ программных объектов строго привязано к одной (или нескольким) функциональным переменным, которые в конечном итоге выйдут за пределы области видимости (когда блок, которому они принадлежат, завершится).
Примечание: это немного оптимистично, используя подсчет ссылок ( Rc
или Arc
) можно формировать циклы ссылок и, таким образом, вызывать утечки памяти, и в этом случае ресурсы, привязанные к циклу, могут никогда не быть освобождены.