Apa yang dimiliki Rust daripada pengumpul sampah?

96

Saya mengerti Rust tidak memiliki pengumpul sampah dan saya bertanya-tanya bagaimana memori dibebaskan ketika pengikatan keluar dari ruang lingkup.

Jadi dalam contoh ini, saya memahami bahwa Rust mengambil kembali memori yang dialokasikan ke 'a' ketika keluar dari ruang lingkup.

{
    let a = 4
}

Masalah yang saya hadapi dengan ini, pertama bagaimana ini terjadi, dan kedua bukankah ini semacam pengumpulan sampah? Apa bedanya dengan pengumpulan sampah 'biasa'?

rix
sumber
12
"Umur objek deterministik". Mirip dengan C ++.
pengguna2864740
@ user2864740 Panduan itu sudah kedaluwarsa. Pengganti modern mungkin adalah doc.rust-lang.org/book/references-and-borrowing.html .
Veedrac

Jawaban:

75

Pengumpulan sampah biasanya digunakan secara berkala atau sesuai permintaan, seperti jika tumpukan mendekati penuh atau di atas ambang batas tertentu. Ia kemudian mencari variabel yang tidak digunakan dan membebaskan memorinya, tergantung pada algoritmanya .

Rust akan tahu ketika variabel keluar dari ruang lingkup atau masa pakainya berakhir pada waktu kompilasi dan dengan demikian memasukkan LLVM / instruksi perakitan yang sesuai untuk membebaskan memori.

Karat juga memungkinkan beberapa jenis pengumpulan sampah, seperti penghitungan referensi atom .

Ayonix
sumber
Dengan mengalokasikan memori saat memperkenalkan variabel dan membebaskan memori saat memori tidak lagi diperlukan? Saya tidak benar-benar tahu apa yang ingin Anda katakan dengan itu. Mungkin kami memiliki pendapat berbeda tentang apa itu GC.
Ayonix
1
Pertanyaannya adalah bagaimana pendekatan Rust berbeda dari GC biasa. Jadi saya menjelaskan apa itu GC dan bagaimana Rust melakukannya tanpa GC.
Ayonix
1
doc.rust-lang.org/book/the-stack-and-the-heap.html menjelaskannya dengan cukup baik. Ya, banyak hal yang ada di tumpukan tetapi apalagi indikatornya tidak memadai (lihat Kotak). Saya meninggalkan itu demi kesederhanaan, karena pertanyaannya umumnya
diajukan
1
@Amomum Sebenarnya Rust tidak memiliki new()fungsi yang diurapi seperti C, mereka hanya fungsi statis, dan khususnya sesuatu seperti let x = MyStruct::new()membuat objeknya di tumpukan. The nyata indikator alokasi heap adalah Box::new()(atau salah satu struktur yang bergantung pada Box).
Mario Carneiro
1
Bahasa lain apa yang menangani manajemen memori dengan cara yang mirip dengan Rust?
still_dreaming_1
43

Ide dasar dari pengelolaan sumber daya (termasuk memori) dalam sebuah program, apapun strateginya, adalah bahwa sumber daya yang terkait dengan "objek" yang tidak terjangkau dapat diperoleh kembali. Di luar memori, sumber daya tersebut dapat berupa kunci mutex, pegangan file, soket, koneksi database ...

Bahasa dengan pengumpul sampah secara berkala memindai memori (dengan satu atau lain cara) untuk menemukan objek yang tidak digunakan, melepaskan sumber daya yang terkait dengannya, dan terakhir melepaskan memori yang digunakan oleh objek tersebut.

Rust tidak memiliki GC, bagaimana cara mengelolanya?

Rust memiliki kepemilikan. Dengan menggunakan sistem tipe affine , ia melacak variabel mana yang masih memegang sebuah objek dan, ketika variabel seperti itu keluar dari ruang lingkup, memanggil destruktornya. Anda dapat melihat sistem tipe affine berlaku cukup mudah:

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

Hasil:

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

yang secara sempurna menggambarkan bahwa di setiap titik waktu, di tingkat bahasa, kepemilikan dilacak.

Kepemilikan ini bekerja secara rekursif: jika Anda memiliki Vec<String>(yaitu, deretan string dinamis), maka masing String- masing dimiliki Vecolehnya sendiri yang dimiliki oleh variabel atau objek lain, dll ... jadi, ketika variabel keluar dari ruang lingkup, ia secara rekursif membebaskan semua sumber daya yang dimilikinya, bahkan secara tidak langsung. Dalam kasus Vec<String>ini berarti:

  1. Melepaskan buffer memori yang terkait dengan masing-masing String
  2. Melepaskan buffer memori yang terkait dengan buffer Vecitu sendiri

Dengan demikian, berkat pelacakan kepemilikan, masa pakai SEMUA objek program secara ketat terikat pada satu (atau beberapa) variabel fungsi, yang pada akhirnya akan keluar dari ruang lingkup (ketika blok tempat mereka berada berakhir).

Catatan: ini agak optimis, dengan menggunakan penghitungan referensi ( Rcatau Arc) dimungkinkan untuk membentuk siklus referensi dan dengan demikian menyebabkan kebocoran memori, dalam hal ini sumber daya yang terkait dengan siklus tersebut mungkin tidak akan pernah dirilis.

Matthieu M.
sumber
2
"Bahasa dengan Pengumpul Sampah memindai memori secara berkala (dengan satu atau lain cara)". Banyak yang melakukan tetapi itu tidak benar secara umum. Pengumpul sampah secara real-time memindai secara bertahap, bukan secara berkala. Referensi penghitungan bahasa seperti Mathematica tidak memindai sama sekali.
JD
@JonHarrop: Saya tidak menghitung penghitungan referensi sebagai mekanisme Pengumpulan Sampah yang lengkap karena harus ditambah untuk menghindari siklus bocor. Adapun perbedaan inkremental / periodik, mungkin perintah bahasa Inggris saya yang buruk, tetapi saya gagal untuk melihat bagaimana periodik tidak mencakup kasus inkremental ... Saya pikir bahwa "(satu atau lain cara)" bit cukup menyampaikan banyak variasi ada pendekatan. Bagaimanapun, jika Anda memiliki cara yang lebih baik untuk mendeskripsikan Pengumpulan Sampah secara ringkas, mohon saran. Namun, saya tidak berniat meluncurkan diri saya dalam penjelasan yang lengkap: Saya tidak memenuhi syarat untuk itu.
Matthieu M.
1
"Saya tidak menghitung penghitungan referensi sebagai mekanisme pengumpulan sampah yang lengkap karena harus ditambah untuk menghindari siklus bocor". RC secara konvensional dianggap sebagai bentuk GC. Di Mathematica dan Erlang, misalnya, siklus tidak dapat dibuat dengan desain sehingga RC tidak bocor. Untuk perspektif tingkat tinggi, lihat "Teori terpadu tentang pengumpulan sampah" cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
JD
@JonHarrop: Benar, jika tidak ada siklus yang memungkinkan maka RC tidak bisa bocor.
Matthieu M.
2
"Saya gagal untuk melihat bagaimana periodik tidak mencakup kasus inkremental". Algoritma stop the world akan dianggap periodik sedangkan tricolor marking dianggap incremental, misalnya. Mereka berlawanan dalam konteks ini.
JD
6

Dengan bahasa yang mengharuskan Anda mengelola memori secara manual, perbedaan antara tumpukan dan heap menjadi penting. Setiap kali Anda memanggil suatu fungsi, cukup ruang yang dialokasikan di stack untuk semua variabel yang ada dalam cakupan fungsi itu. Saat fungsi tersebut kembali, bingkai tumpukan yang terkait dengan fungsi itu "dikeluarkan" dari tumpukan, dan memori dibebaskan untuk digunakan di masa mendatang.

Dari sudut pandang praktis, pembersihan memori yang tidak disengaja ini digunakan sebagai sarana penyimpanan memori otomatis yang akan dihapus di akhir ruang lingkup fungsi.

Informasi lebih lanjut tersedia di sini: https://doc.rust-lang.org/book/the-stack-and-the-heap.html

Swiss
sumber
3
Meskipun menggunakan tumpukan berguna, masa pakai objek deterministik masih dapat ditangani jika semua nilai 'dibuat di heap'. Jadi ini adalah detail implementasi; belum tentu merupakan strategi bahasa.
pengguna2864740
2
Anda tetap menggunakan kata itu. Saya tidak berpikir itu berarti apa yang Anda pikirkan.
Swiss
Berarti apa yang ingin saya ungkapkan ; menjadi kebalikan dari masa hidup non-deterministik. Buatlah penawaran untuk frase yang lebih baik.
pengguna2864740
Terima kasih atas jawabannya, saya telah memberikan poin ke yang pertama hanya karena itu dikirim terlebih dahulu. Informasi tersebut berguna dan valid.
rix
@ user2864740 Masa pakai objek deterministik mengacu pada kemampuan untuk mengetahui dengan tepat kapan memori objek akan dihapus setelah destruktornya dipanggil. Ini tidak ada hubungannya dengan bagaimana destruktor itu dipanggil sejak awal. Anda terus mengemukakan istilah yang sama berulang kali meskipun itu tidak memiliki signifikansi langsung pada pertanyaan tersebut.
Swiss