Подтвердить что ты не робот

Что делает ржавчина вместо сборщика мусора?

Довольно простой вопрос, но я новичок в Rust/C/С++ и т.д. Я понимаю, что у Rust нет сборщика мусора, и мне интересно, как освобождается память, когда привязка выходит за рамки.

Итак, в этом примере я понимаю, что Rust восстанавливает память, выделенную "a", когда она выходит из области видимости.

{
    let a = 4
}

Проблема, с которой я столкнулась, - это, во-первых, как это происходит, а во-вторых, разве это не какая-то сборка мусора? Как он отличается от "типичной" коллекции мусора?

Извинения, я знаю, что это несколько элементарно, но я исхожу из динамических языков.

4b9b3361

Ответ 1

Сбор мусора обычно используется периодически или по запросу, например, если куча близка к полному или выше некоторого порога. Затем он ищет неиспользуемые переменные и освобождает их память в зависимости от алгоритма .

Rust будет знать, когда переменная выходит из области видимости или заканчивается ее время жизни во время компиляции и, таким образом, вставляет соответствующие инструкции LLVM/assembly для освобождения памяти.

Rust также допускает некоторую сборку мусора, например атомный подсчет ссылок.

Ответ 2

Основная идея управления ресурсами (включая память) в программе, независимо от стратегии, заключается в том, что ресурсы, привязанные к недоступным "объектам", могут быть восстановлены. Помимо памяти эти ресурсы могут быть блокировками мьютексов, файлами, сокетами, подключениями к базе данных...

Языки с сборщиком мусора периодически проверяют память (так или иначе), чтобы найти неиспользуемые объекты, освободить связанные с ними ресурсы и, наконец, освободить память, используемую этими объектами.

У Rust нет GC, как он справляется?

Руста имеет право собственности. Используя Affine Type System, он отслеживает, какая переменная все еще держится на объекте, и, когда такая переменная выходит за пределы области, вызовы являются деструкторами. Вы можете легко увидеть систему Affine Type System:

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), можно создавать циклы ссылок и, следовательно, вызывать утечки памяти, и в этом случае ресурсы, привязанные к циклу, могут никогда не быть выпущены.

Ответ 3

С языком, где вы должны вручную управлять памятью, различие между стеком и кучей становится критическим. Каждый раз, когда вы вызываете функцию, в стеке выделяется достаточно места для всех переменных, содержащихся в пределах этой функции. Когда функция возвращается, фрейм стека, связанный с этой функцией, "выталкивается" из стека, и память освобождается для использования в будущем.

С практической точки зрения, эта непреднамеренная чистка памяти используется как средство автоматической памяти, которая будет очищена в конце области действия.

Здесь имеется более подробная информация: https://doc.rust-lang.org/book/the-stack-and-the-heap.html