ProgramlamaBackend geliştirici

Rust'da slice'ların mekanizması nasıl çalışır, hangi slice türleri vardır, güvenlik nasıl sağlanır ve slice'ın sınırlarını aşmaya çalışıldığında ne olur?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

Rust'da Slice (kesit) koleksiyonun bir bölümünün dinamik temsili olup, elemanlar bellekte ardışık olarak yer alır. Tipik bir kesit örneği &[T] veya &mut [T]'dir. Slice'lar verilere sahip değildir, dış bir tampon üzerinde referans verirler. Tüm kesitlerin bir uzunluğu vardır ve bu uzunluk referans ile birlikte saklanır.

Ana türler:

  • &[T] — değiştirilemeyen kesit
  • &mut [T] — değiştirilebilir kesit
  • String'ler için: &str (aslında, her zaman geçerli UTF-8 olan bir byte slice)

Slice güvenliği derleyici ve çalışma zamanı düzeyinde sağlanır: kesitin sınırlarının ötesindeki bir elemana erişmeye yönelik her türlü girişim, çalışma zamanında paniğe (panic) neden olacaktır; C/C++ gibi bellekle ilgili gevşek hatalar meydana gelmeyecektir.

Örnek:

let v = vec![1, 2, 3, 4, 5]; let s: &[i32] = &v[1..4]; // kesit, 2, 3, 4 elemanlarına referans verir println!("{:?}", s); // [2, 3, 4] // s[3]; // panic! (sınır dışına çıkma)

Kandırmaca soru

Sslice'lar boş olabilir mi? Boş bir slice ile None arasındaki fark nedir?

Cevap: Evet, slice'lar boş olabilir (&[]), bu sıfır uzunlukta veri parçasına bir referans olduğunu ifade eder, ancak bu None ile eşdeğer değildir. Boş bir slice kullanımı güvenlidir, Option<&[T]> ise "kesitin olup olmadığını" ayırt etmek için kullanılır.

Örnek:

let s: &[i32] = &[]; assert!(s.is_empty()); // Slice'ın hiç olmayabileceği durumlarda Option<&[i32]> kullanılır.

Konu hakkında bilgi eksikliğinden kaynaklanan gerçek hata örnekleri


Hikaye

Büyük bir log servisinde bir programcı kullanıcı verilerinden dinamik olarak hesaplanan bir aralıkta slice aldı. Slice'ın hatalı hesaplanmasında (örneğin, start > end veya end > len ise) kod testlerde çalıştı ama üretimde "panic" oluşturup yoğunluk zirvesinde süreci durdurdu.


Hikaye

İç kütüphanede concurremt-hashing kullanarak &mut [T] kullandı ve bir dizi üzerinde birkaç thread farklı slice'lar aldı. Bir thread kesiti değiştirirken diğeri aynı belleği referans alan başka bir kesit aldı. Program derleniyordu ama yanlış bölmeden kaynaklanan UB (Undefined Behavior) oluşabiliyordu, eğer slice'lar örtüşüyorsa.


Hikaye

Sistemsel ağ paketlerini ayrıştırmak için bir kesit güvensiz bir şekilde (raw pointer ve from_raw_parts) oluşturuldu. Geliştirici giriş paketinin uzunluğunun doğruluğunu kontrol etmeyi unuttu. Sonuç olarak, sınırların dışına okuma girişimi uygulamanın çökmesine ve potansiyel bir güvenlik açığına (potential OOB access) yol açtı; bu sorun güvenli slice'ların doğru uygulanmasıyla önlenebilir.