Rust dilinde bellek yönetimi, düşük seviyeli programlamada en karmaşık sorunlardan biri olarak kabul edilmiştir. Rust'tan önce birçok dil manuel bellek yönetimi gerektiriyordu (C/C++ gibi), bu da bellek sızıntılarına ve veri bozulmalarına yol açıyordu. Rust, bu soruna farklı bir yaklaşımla geldi; Vec<T> gibi koleksiyonlar bellek yönetimini otomatik ve güvenli bir strateji ile gerçekleştiriyor, tahsis, yeniden boyutlandırma (resize) ve bellek serbest bırakma anlarını sahiplik ve ödünç alma sistemi aracılığıyla kontrol ediyor.
Sorun şu ki, çoğu dil ya tahsisat detaylarını (GC) fazla soyutluyor ya da programcıyı her şeyden sorumlu kılıyor (malloc/free). Dinamik dizilerde bellek sızıntılarına ve dizinin sınırlarının aşılmasına dikkat etmek, ayrıca sahiplik ihlali yapmamak son derece önemlidir.
Çözüm Rust'ta, güvenli soyutlamalar aracılığıyla otomasyondur. Vec<T> bellek yığınında tahsis eder, boyutunu dinamik olarak artırır (genellikle üssel büyüme ile) ve kapsamdan çıktığında her şeyi serbest bırakır (RAII).
Kod örneği:
fn main() { let mut v: Vec<i32> = Vec::new(); v.push(1); v.push(2); v.push(3); // Eklenmesi boyut artışına ve bellek yeniden tahsisine neden olur println!("Vector: {:?}", v); // main'den çıkıldığında bellek otomatik olarak serbest bırakılır }
Anahtar özellikler:
Vec<T> bellek tahsisini önceden yapar ve gerektiğinde yeniden tahsis ederVec'e eleman eklerken dizinin büyüme karmaşıklığı nedir?
Genellikle push karmaşıklığı amortize O(1)dir, ancak dizi taşarsa yeni bir bellek alanı tahsis edilir (boyut neredeyse iki katına çıkar) ve tüm elemanlar kopyalanır. Bu durum, işlemin O(n) olduğu tek istisnadır.
v[index] ile aralık dışında bir eleman almaya çalışırsak ne olur?
Kare parantez kullanmak sınırları aşmakta paniklemeye yol açar. Hatanın güvenli bir şekilde işlenmesine olanak tanıyan .get() yöntemini kullanmalısınız.
let element = v.get(10); // Yoksa None
Bir Vec elemanına referans, vektör büyüdüğünde (resize) kullanılabilir mi?
Hayır, bir vektörün boyutu değiştiğinde (örneğin, taşma olduğunda push ile) tüm bellek taşınabilir ve eski referanslar geçersiz hale gelir — bir derleme hatası meydana gelir (veya manuel kullanıyorsanız unsafe blokta tanımsız davranış mümkündür).
Bir geliştirici Vec<T> temelinde bir mesaj önbelleği uygular ve dışarıya elemanların referanslarını verir. Yeni bir ekleme sonrası bellek yeniden tahsis edilir ve tüm mevcut referanslar "askıda" kalır. Bu, uygulamanın çökmesine yol açar.
Artılar:
Eksiler:
Ya içsel eleman tanımlaması (indeks/anahtar + geçerlilik kontrolü) kullanılır ya da yalnızca kopyalar/immutable değerler döndürülür, Vec üzerindeki uzun ömürlü referansların tutulmasına izin verilmez.
Artılar:
Eksiler: