Rust'un çöp toplayıcı yerine ne var?


95

Rust'un bir çöp toplayıcısına sahip olmadığını anlıyorum ve bir bağlama kapsam dışına çıktığında belleğin nasıl serbest kaldığını merak ediyorum.

Yani bu örnekte, Rust'un kapsam dışına çıktığında 'a'ya ayrılan belleği geri aldığını anlıyorum.

{
    let a = 4
}

Bununla yaşadığım sorun, öncelikle bunun nasıl gerçekleştiği ve ikincisi bu bir tür çöp toplama değil mi? 'Tipik' çöp toplamadan farkı nedir?


12
"Deterministik nesne yaşam süreleri". C ++ ile benzerdir.
user2864740

@ user2864740 Bu kılavuz çok eski. Modern yedek muhtemelen doc.rust-lang.org/book/references-and-borrowing.html olacaktır .
Veedrac

Yanıtlar:


74

Çöp toplama genellikle periyodik olarak veya istendiğinde kullanılır, örneğin yığının dolmaya yakın veya bir eşiğin üstünde olması gibi. Daha sonra kullanılmayan değişkenleri arar ve algoritmaya bağlı olarak hafızasını serbest bırakır .

Rust, değişkenin kapsam dışına çıktığını veya kullanım süresinin derleme zamanında bittiğini bilir ve böylece belleği boşaltmak için karşılık gelen LLVM / montaj talimatlarını ekler.

Rust ayrıca atomik referans sayımı gibi bir tür çöp toplamaya da izin verir .


Değişkenleri tanıtırken bellek ayırarak ve belleğe artık ihtiyaç kalmadığında belleği serbest bırakarak mı? Bununla ne söylemek istediğini gerçekten bilmiyorum. Belki de GC'nin ne olduğu konusunda farklı fikirlere sahibiz.
Ayonix

1
Sorusu, Rust'un yaklaşımının tipik bir GC'den ne kadar farklı olduğudur. Bu yüzden bir GC'nin ne olduğunu ve Rust'un bunu GC olmadan nasıl yaptığını açıkladım.
Ayonix

1
doc.rust-lang.org/book/the-stack-and-the-heap.html bunu oldukça iyi açıklıyor. Evet, birçok şey yığının içindedir, ancak yeterli gösterge de değildir (Kutuya bakınız). Soru genel olarak sorulduğu için bunu basitlik
adına dışarıda bıraktım

1
@Amomum Aslında Rust'un new()C gibi herhangi bir anointed işlevi yoktur, bunlar sadece statik işlevlerdir ve özellikle de benzeri bir şey let x = MyStruct::new()nesnesini yığın üzerinde oluşturur. Gerçek yığın ayırma göstergesi olan Box::new()(ya da kutu bağımlı yapılar herhangi biri).
Mario Carneiro

1
Başka hangi diller bellek yönetimini Rust'a benzer şekilde ele alıyor?
still_dreaming_1

43

Stratejisi ne olursa olsun, bir programdaki kaynakları (bellek dahil) yönetmenin temel fikri, ulaşılamayan "nesnelere" bağlı kaynakların geri kazanılabilmesidir. Belleğin ötesinde, bu kaynaklar muteks kilitler, dosya tanıtıcıları, soketler, veritabanı bağlantıları olabilir ...

Çöp toplayıcıya sahip diller, kullanılmayan nesneleri bulmak, bunlarla ilişkili kaynakları serbest bırakmak ve son olarak bu nesneler tarafından kullanılan belleği serbest bırakmak için belleği (öyle veya böyle) düzenli aralıklarla tarar.

Rust'un GC'si yok, nasıl yönetiyor?

Rust'un mülkiyeti var. Afin tipi bir sistem kullanarak , hangi değişkenin hala bir nesneyi tuttuğunu izler ve bu tür bir değişken kapsam dışına çıktığında yıkıcısını çağırır. Afin tip sistemin etkili olduğunu oldukça kolay görebilirsiniz:

fn main() {
    let s: String = "Hello, World!".into();
    let t = s;
    println!("{}", s);
}

Getiri:

<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;
                     ^

bu, herhangi bir zamanda, dil düzeyinde, sahipliğin izlendiğini mükemmel bir şekilde göstermektedir.

Bu sahiplik özyinelemeli olarak çalışır: eğer bir Vec<String>(yani dinamik dizeler dizisine) sahipseniz , o zaman her Stringbiri Vecbir değişkene veya başka bir nesneye vb. Sahip olunur ... dolayısıyla, bir değişken kapsam dışına çıktığında, dolaylı da olsa sahip olduğu tüm kaynakları yinelemeli olarak serbest bırakır. Bu durumda Vec<String>şu anlama gelir:

  1. Her biri ile ilişkili bellek arabelleğini serbest bırakma String
  2. VecKendisiyle ilişkili bellek tamponunu serbest bırakmak

Bu nedenle, sahiplik izleme sayesinde, TÜM program nesnelerinin yaşam süresi bir (veya birkaç) işlev değişkenine sıkı sıkıya bağlıdır ve sonuçta kapsam dışına çıkacaktır (blok sona ait olduğunda).

Not: Bu biraz iyimserdir, referans sayma ( Rcveya Arc) kullanarak referans döngüleri oluşturmak ve dolayısıyla bellek sızıntılarına neden olmak mümkündür, bu durumda döngüye bağlı kaynaklar asla serbest bırakılmayabilir.


2
"Çöp Toplayıcıya sahip diller, düzenli aralıklarla belleği tarar (öyle veya böyle)". Birçoğu yapıyor ama bu genel olarak doğru değil. Gerçek zamanlı çöp toplayıcılar, düzenli aralıklarla değil, aşamalı olarak tarama yapar. Mathematica gibi referans sayma dilleri hiç tarama yapmaz.
JD

@JonHarrop: Referans saymayı tam bir Çöp Toplama mekanizması olarak saymıyorum çünkü döngülerin sızmasını önlemek için tamamlanması gerekiyor. Artımlı / periyodik farka gelince, bu benim İngilizce bilgim zayıf olabilir, ancak periyodik olarak artan durumu kapsamadığını göremiyorum ... "(şu veya bu şekilde)" bitinin pek çok farklı yaklaşımlar mevcuttur. Her halükarda, Çöp Toplama'yı kısa ve öz bir şekilde tanımlamanın daha iyi bir yoluna sahipseniz, lütfen önermeyin. Bununla birlikte, kendimi tam anlamıyla açıklamak gibi bir niyetim yok: Bunun için vasıfsızım.
Matthieu M.

1
"Referans saymayı tam bir Çöp Toplama mekanizması olarak saymıyorum çünkü döngülerin sızmasını önlemek için tamamlanması gerekiyor". RC, geleneksel olarak bir GC şekli olarak kabul edilir. Örneğin Mathematica ve Erlang'da çevrimler tasarımla yaratılamaz, bu yüzden RC sızmaz. Üst düzey bir bakış açısı için, bkz. "Birleştirilmiş çöp toplama teorisi" cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
JD

@JonHarrop: Doğru, eğer döngü mümkün değilse RC sızıntı yapamaz.
Matthieu M.

2
"Periyodik durumun artımlı durumu nasıl kapsamadığını göremiyorum". Örneğin, dünyayı durdur algoritmaları periyodik olarak kabul edilirken, üç renkli işaretleme artımlı olarak kabul edilir. Bu bağlamda karşıtlar.
JD

6

Belleği manuel olarak yönetmeniz gereken bir dille, yığın ve yığın arasındaki ayrım kritik hale gelir. Bir işlevi her çağırdığınızda, yığında o işlevin kapsamında bulunan tüm değişkenler için yeterli alan ayrılır. İşlev geri döndüğünde, bu işlevle ilişkili yığın çerçevesi yığından "çıkar" ve bellek ileride kullanılmak üzere serbest bırakılır.

Pratik bir bakış açısıyla, bu kasıtsız bellek temizliği, işlevin kapsamının sonunda temizlenecek olan otomatik bellek depolama aracı olarak kullanılır.

Burada daha fazla bilgi var: https://doc.rust-lang.org/book/the-stack-and-the-heap.html


3
Yığın kullanımı kullanışlı olsa da, tüm değerler 'yığın üzerinde yaratılmışsa' deterministik nesne yaşam süreleri yine de işlenebilir. Dolayısıyla bir uygulama detayıdır; bir dil stratejisi olması gerekmez.
user2864740

2
O kelimeyi kullanmaya devam ediyorsun. Bunun düşündüğün anlamının ne anlama geldiğini sanmıyorum.
İsviçre

İfade etmek istediğim anlamına gelir ; deterministik olmayan yaşamların zıttı olmak. Daha iyi bir ifade için bir teklifte bulunun.
user2864740

Cevabınız için teşekkürler, puanları birincisine sırf ilk gönderildiği için verdim. Bilgiler aynı derecede faydalı ve geçerlidir.
rix

@ user2864740 Belirleyici nesne yaşam süreleri, yıkıcı çağrıldıktan sonra nesnenin belleğinin tam olarak ne zaman temizleneceğini söyleyebilmeyi ifade eder. En başta bu yıkıcının nasıl çağrıldığıyla hiçbir ilgisi yok. Soru için doğrudan bir anlamı olmamasına rağmen aynı terimi tekrar tekrar gündeme getiriyorsunuz.
İsviçre
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.