Tüm Rust rehberleri
TEKNİK REHBER BELLEK OWNERSHIP 2026

Ownership & Borrowing
Borrow checker'ı anlamak

Rust'ın bellek güvenliğinin kalbi: sahiplik, move semantiği, ödünç alma ve derleme-zamanı borrow checker — C++ unique_ptr ve RAII ile karşılaştırmalı.

00 Neden ownership?

C bellek hatalarını çalışma zamanına bırakır, GC ise runtime maliyet ekler — Rust üçüncü yolu seçer: derleme-zamanı sahiplik.

Bir C/C++ programcısı olarak bellek hatalarının taksonomisini ezbere biliyorsundur: use-after-free (serbest bırakılmış belleğe erişim), double-free (aynı bloğu iki kez serbest bırakma), memory leak (hiç bırakmama) ve dangling pointer (ömrü bitmiş nesneye işaret eden pointer). Bu hataların ortak özelliği: derleyici sessizdir, sorun çalışma zamanında — çoğu zaman üretimde — patlar. Valgrind, ASan ve code review bunları azaltır ama matematiksel bir garanti vermez.

Geleneksel olarak iki çözüm vardı. Birincisi manuel yönetim (C/C++): hızlı ve deterministik, ama güvenliği programcının disiplinine bırakır. İkincisi garbage collection (Java, Go, C#): güvenli, ama runtime'da tarama döngüleri, durdur-dünya (stop-the-world) duraklamaları ve öngörülemez gecikme getirir — gömülü ve gerçek-zamanlı sistemlerde kabul edilemez.

Rust üçüncü yolu seçer: belleği derleme zamanında bir sahiplik (ownership) modeliyle yönetir. Çalışma zamanında GC yoktur, ekstra metadata yoktur; kontroller derleyicide yapılır ve geçen kod sıfır-maliyet (zero-cost) çalışır. Aşağıdaki C örneği klasik bir use-after-free içerir — Rust'ta karşılığı derlenmez bile.

danger.c
// C: derleyici hiçbir şikayet etmez, runtime'da UB.
char *p = malloc(16);
strcpy(p, "merhaba");
free(p);
printf("%s\n", p);   // use-after-free — patlayabilir, patlamayabilir
main.rs
fn main() {
    let s = String::from("merhaba");
    drop(s);             // belleği elle bıraktık (genelde gerek yok)
    println!("{s}");     // HATA: borrow of moved value: `s`
}
// error[E0382]: derleyici durdurur; runtime UB asla oluşmaz.
NOT

Rust'ın garantisi tek bir cümleyle: güvenli (safe) kodda veri yarışı, dangling pointer ve use-after-free derleme zamanında imkânsızdır. Bu garantilerden çıkmak istersen unsafe blok kullanırsın — ama bu açık ve aranabilir bir karardır.

Bu bölümde

  • C bellek hataları (use-after-free, double-free, leak, dangling) derleme zamanında yakalanmaz.
  • GC güvenlik sağlar ama runtime tarama ve öngörülemez duraklama maliyeti getirir.
  • Rust üçüncü yol: sahiplik modeli ile derleme-zamanı, sıfır-maliyet bellek güvenliği.
  • Tüm bu garantiler "safe" kod içindir; bilinçli olarak unsafe ile devre dışı bırakılabilir.

01 Ownership kuralları

Tüm modelin üç kurala indiği nokta — bunları içselleştirince borrow checker artık düşman değil refleks olur.

Rust'ın bütün bellek modeli üç basit aksiyoma dayanır:

Kural 1Her değerin (value) bir sahibi (owner) vardır — sahibi tutan değişkendir.
Kural 2Bir değerin aynı anda yalnızca tek sahibi olabilir.
Kural 3Sahip scope'tan çıktığında değer otomatik olarak drop edilir (kaynak bırakılır).

Üçüncü kural bir C++ programcısına RAII gibi gelmeli — çünkü tam olarak öyle. Fark şu: C++'ta RAII bir kütüphane deseni ve programcı disiplinidir; Rust'ta dilin değişmez kuralıdır ve sahiplik takibi derleyici tarafından zorlanır.

Stack vs heap: nerede yaşar?

Sabit boyutlu ve Copy olan değerler (i32, bool, char) stack'te yaşar; ucuz kopyalanır. String ise üç alandan oluşan bir fat değerdir: stack'te bir başlık (heap'e pointer + uzunluk + kapasite), asıl bayt verisi heap'te. Sahip scope'tan çıkınca heap belleği String'in Drop implementasyonu tarafından serbest bırakılır.

main.rs
fn main() {
    let n = 42;                       // stack: i32, Copy
    {
        let s = String::from("selam"); // başlık stack'te, "selam" heap'te
        println!("{s} / {n}");
    } // s burada scope'tan çıktı -> String::drop çağrıldı, heap free

    println!("{n}"); // n hâlâ geçerli; s artık yok
}
let s = String::from(...)  →  scope sonu  →  drop(s)  →  heap free
NOT

C++'ta delete unutmak leak, iki kez çağırmak double-free üretir. Rust'ta drop'u derleyici yerleştirir; ne unutabilirsin ne de elle iki kez çağırabilirsin — sahiplik kuralları double-drop'u baştan engeller.

Bu bölümde

  • Üç kural: tek sahip vardır, aynı anda tek sahip olur, sahip scope'tan çıkınca değer drop edilir.
  • Kural 3 = derleyicinin zorladığı, garantili RAII.
  • String stack başlığı (ptr/len/cap) + heap verisi olan fat bir değerdir.
  • Drop çağrısını derleyici otomatik yerleştirir; leak veya double-free elle yapılamaz.

02 Move semantiği

Rust'ta varsayılan atama move'dur, kopya değil — ve move sonrası kaynak değişken kullanılamaz hale gelir.

C++'ta auto b = a; varsayılan olarak kopyalar (copy constructor); taşımak istersen açıkça std::move(a) yazarsın. Rust tam tersini yapar: non-Copy tipler için varsayılan atama move'dur. Move sırasında stack başlığı bit-bit yeni değişkene aktarılır ve eski değişken geçersizleştirilir. Heap verisi kopyalanmaz — yalnızca tek geçerli sahip vardır (Kural 2).

main.rs
fn main() {
    let a = String::from("veri");
    let b = a;            // MOVE: başlık a'dan b'ye taşındı, a artık geçersiz

    println!("{b}");     // OK
    println!("{a}");     // HATA[E0382]: borrow of moved value: `a`
}

Bu neden hatadır? Çünkü ikisi de geçerli kalsaydı, ikisi de aynı heap bloğunu işaret eder, ikisi de scope sonunda drop çalıştırır — klasik double-free. Rust kaynağı move ile geçersizleştirerek bu durumu kökünden imkânsız kılar. C++'ın "moved-from" nesnesi geçerli-ama-belirsiz durumdadır; Rust'ta moved-from değer derleyici tarafından kullanılamaz ilan edilir.

Fonksiyona move

Bir değeri fonksiyona değer olarak (by value) geçirmek de move'dur. Çağrıdan sonra kaynak değişken artık senin değildir.

main.rs
fn yut(s: String) {
    println!("yutuldu: {s}");
} // s burada drop edilir

fn main() {
    let t = String::from("merhaba");
    yut(t);              // t fonksiyona MOVE edildi
    // println!("{t}");  // HATA: t artık geçersiz
}
Dilb = a varsayılanıTaşımak için
C++copy (kopya kurucu)std::move(a)
Rustmove (kaynak geçersizleşir)zaten varsayılan

Bu bölümde

  • Non-Copy tiplerde atama ve fonksiyon argümanı varsayılan olarak move'dur.
  • Move sonrası kaynak değişken derleyicide geçersizdir — kullanımı E0382 hatası verir.
  • Move heap verisini kopyalamaz; yalnızca stack başlığını taşır (ucuz).
  • Tek-sahip kuralı double-free'yi tasarımdan eler; C++'ın "moved-from" belirsizliği yoktur.

03 Copy vs Clone

Bazı tipler move yerine sessizce kopyalanır (Copy); derin kopya istiyorsan açıkça .clone() dersin.

Her tip move semantiğine uymaz. Sabit boyutlu, tamamen stack'te yaşayan ve "bitlerini kopyalamak yeterli" olan tipler Copy trait'ini implement eder: i32, u64, bool, char, f64, ve yalnızca Copy alanlardan oluşan tuple/struct'lar. Bunlarda let b = a; kaynağı geçersizleştirmez — çünkü ucuz bir bit kopyası yapılır ve iki bağımsız değer ortaya çıkar, double-free riski yoktur.

main.rs
fn main() {
    let x = 5;
    let y = x;        // COPY: i32 Copy'dir, x hâlâ geçerli
    println!("{x} {y}");  // OK -> 5 5
}

Clone: açık ve potansiyel pahalı

String, Vec<T>, HashMap gibi heap sahibi tipler Copy değildir; çünkü ucuz bit kopyası iki sahip yaratır. Gerçek bir derin kopya istiyorsan .clone() çağırırsın — bu, heap verisini yeni bir blok olarak çoğaltır. Çağrı açıktır: kodda .clone() görmek "burada heap tahsisi/kopyası var" demektir.

main.rs
fn main() {
    let a = String::from("veri");
    let b = a.clone();   // DERİN kopya: yeni heap bloğu, ayrı veri

    println!("{a} | {b}");  // her ikisi de geçerli -> veri | veri
}
ÖzellikCopyClone
Tetiklemeörtük (atama anında)açık (.clone())
Maliyetucuz bit kopyasıkeyfi (heap, derin)
Tipik tipleri32, bool, char, &TString, Vec, HashMap
İlişkiCopy ⊂ Clone (Copy ise Clone de olmalı)tek başına olabilir
DİKKAT

Borrow checker hatasından kurtulmak için refleks olarak .clone() serpiştirmek yaygın bir acemi tuzağıdır. Her clone bir tahsis/kopya maliyetidir. Doğru çözüm çoğu zaman borrow etmektir (sonraki bölümler) — clone'u gerçekten ayrı bir kopya gerektiğinde sakla.

Bu bölümde

  • Copy tipler (sabit boyut, stack) atamada örtük kopyalanır; kaynak geçerli kalır.
  • Heap sahibi tipler Copy değildir; derin kopya için açık .clone() gerekir.
  • .clone() kodda görünür bir maliyet işaretidir.
  • Hatayı clone ile susturmak yerine genelde borrow etmek doğru çözümdür.

04 Sahipliği fonksiyonlarla taşımak

Sadece move ile çalışmak değeri fonksiyonlara "ver-geri al" döngüsüne sokar — bu hantallık borrowing'in doğuş sebebidir.

Move semantiği tutarlıdır ama saf haliyle kullanışsızdır. Bir String'i bir fonksiyona verip sonra ana fonksiyonda kullanmaya devam etmek istersen, fonksiyonun onu geri döndürmesi gerekir. Tek bir veri için bu katlanılabilir; ama hem değeri kullanıp hem de bir sonuç döndürmek istediğinde tuple iadelerine boğulursun.

main.rs
// Borrowing yokken: sahipliği al, geri döndür — hantal.
fn uzunluk(s: String) -> (String, usize) {
    let n = s.len();
    (s, n)              // sahipliği çağırana geri verebilmek için s'i iade et
}

fn main() {
    let s = String::from("merhaba");
    let (s, n) = uzunluk(s); // move ettik, geri aldık... yorucu
    println!("'{s}' uzunluğu {n}");
}

Buradaki hantallık tesadüf değil — Rust seni doğal olarak doğru araca itiyor. İhtiyacın olan şey değeri sahiplenmeden, sadece geçici olarak okumak/değiştirmek. Bu da borrowing (ödünç alma): sahibi değiştirmeden bir referans (reference) ödünç vermek.

move-and-return (hantal)  →  borrow &T / &mut T (zarif)
main.rs
// Borrowing ile: sahiplik s'te kalır, sadece referans veririz.
fn uzunluk(s: &String) -> usize {
    s.len()             // okuruz ama sahiplenmeyiz
}

fn main() {
    let s = String::from("merhaba");
    let n = uzunluk(&s);  // & ile ödünç verdik
    println!("'{s}' uzunluğu {n}"); // s hâlâ bizim
}

Bu bölümde

  • Değeri by-value geçirmek sahipliği fonksiyona taşır (move).
  • Sonra kullanmaya devam için değeri geri döndürmek gerekir — sadece move ile kod hantallaşır.
  • Çözüm borrowing: sahibi taşımadan geçici referans vermek.
  • &s ile ödünç verince sahiplik kaynakta kalır, çağrı sonrası değer hâlâ kullanılabilir.

05 Borrowing — &T

Paylaşımlı referans &T: veriyi sahiplenmeden okumana izin verir, aynı anda istediğin kadar olabilir.

&T bir paylaşımlı (shared), değiştirilemez (immutable) referanstır. C'deki const T* ile kavramsal olarak benzer ama kritik bir farkla: Rust'ta referansın işaret ettiği değerin &T yaşadığı sürece geçerli kalacağı (dangling olmayacağı) derleyici tarafından garanti edilir. Bir referans, ödünç verenden daha uzun yaşayamaz.

Aynı veriye aynı anda istediğin kadar &T alabilirsin — okuyucular birbirini rahatsız etmez. Hiçbiri veriyi değiştiremediği için bu güvenlidir.

main.rs
fn main() {
    let s = String::from("merhaba");

    let r1 = &s;      // paylaşımlı borrow
    let r2 = &s;      // ikinci paylaşımlı borrow — sorun yok

    println!("{r1} ve {r2} ve {s}"); // üçü de okuyabilir
}
DİKKAT

Paylaşımlı referans salt okunur bir görünümdür: r1.push_str(...) derlenmez. Değiştirmek için &mut gerekir (sonraki bölüm). C'de const'ı cast'le delebilirsin; Rust'ta &T üzerinden mutasyon hiçbir cast ile mümkün değildir (interior mutability hariç — ileri konu).

Referansları dereference etmek için * kullanılır, ama method çağrıları ve çoğu operatör otomatik dereference (auto-deref) yaptığı için çoğu zaman * yazmazsın:

main.rs
fn topla(v: &Vec<i32>) -> i32 {
    let mut acc = 0;
    for x in v {       // &Vec üzerinde iter; x: &i32
        acc += *x;       // *x ile i32 değerine eriş
    }
    acc
}

Bu bölümde

  • &T paylaşımlı, salt-okunur referanstır; const T*'a benzer ama güvenli.
  • Aynı veriye aynı anda sınırsız sayıda &T alınabilir.
  • Referans, ödünç verdiği değerden daha uzun yaşayamaz — dangling derleme zamanında engellenir.
  • &T üzerinden mutasyon yoktur; auto-deref sayesinde * çoğu zaman gerekmez.

06 &mut T — değiştirilebilir ödünç

Değiştirilebilir referans &mut T veriyi değiştirmene izin verir — ama aynı anda tek tane olabilir.

&mut T ile ödünç aldığın veriyi değiştirebilirsin. Kritik kısıt şudur: bir değer için aynı anda yalnızca bir &mut var olabilir ve bir &mut aktifken aynı veriye başka hiçbir referans (ne & ne &mut) olamaz. Üstelik veriyi &mut ile ödünç verebilmek için değişkenin de mut olması gerekir.

main.rs
fn ekle(s: &mut String) {
    s.push_str(" dünya");   // &mut üzerinden mutasyon serbest
}

fn main() {
    let mut s = String::from("merhaba"); // mut: değişebilir
    ekle(&mut s);
    println!("{s}");     // -> merhaba dünya
}

Tek &mut kuralı neden var?

Cevap: veri yarışını (data race) derleme zamanında imkânsız kılmak. Bir veri yarışı, en az iki erişim aynı belleğe ulaşırken en az biri yazma yapıyor ve erişimler senkronize değilse oluşur. Eğer aynı anda hem bir yazıcı (&mut) hem de başka bir okuyucu/yazıcı olsaydı, klasik data race elimizde olurdu. Rust bunu tip sisteminde yasaklar.

main.rs
fn main() {
    let mut s = String::from("x");

    let r1 = &mut s;
    let r2 = &mut s;   // HATA[E0499]: ikinci &mut, aynı anda olamaz

    println!("{r1} {r2}");
}
NOT

Aynı garanti tek iş parçacığında bile geçerlidir; çünkü mutable aliasing iterator invalidation gibi tek-thread hatalarına da yol açar (örn. bir Vec'i üzerinde iter ederken değiştirmek). C++'ta bu UB; Rust'ta derlenmeyen koddur.

Bu bölümde

  • &mut T veriyi değiştirmeye izin verir; değişken de mut olmalıdır.
  • Aynı anda yalnızca bir &mut olabilir ve o aktifken başka referans olamaz.
  • Bu kuralın amacı veri yarışını ve mutable aliasing'i derleme zamanında elemektir.
  • Tek-thread iterator invalidation gibi hatalar da aynı kural sayesinde imkânsızdır.

07 Borrow checker kuralları

Tüm borrow sistemi tek ilkeye iner: aliasing XOR mutation — ya çok okuyucu, ya tek yazıcı; ikisi birden asla.

Önceki iki bölümün özeti tek bir invariant'tır. Herhangi bir an için, bir veriye ya:

çok sayıda &T (okuyucu)   XOR   tam bir tane &mut T (yazıcı)

Aynı anda hem paylaşımlı okuyucular hem de bir yazıcı olamaz. Bu "aliasing XOR mutability" ilkesi, hem veri yarışlarını hem de bellek bozulmasını (memory corruption) statik olarak engelleyen tek kuraldır. Borrow checker dediğimiz derleyici aşaması tam olarak bunu kontrol eder.

NLL: referanslar son kullanımda biter

Erken Rust'ta bir referans, içinde tanımlandığı blok bitene kadar "canlı" sayılırdı. Bugün Non-Lexical Lifetimes (NLL) sayesinde bir borrow, son kullanıldığı satırda sona erer — kapanış parantezinde değil. Bu sayede aşağıdaki kod derlenir:

main.rs
fn main() {
    let mut s = String::from("x");

    let r = &s;          // paylaşımlı borrow başlar
    println!("{r}");     // r'nin SON kullanımı -> borrow burada biter (NLL)

    let m = &mut s;      // OK: artık aktif paylaşımlı borrow yok
    m.push_str("y");
    println!("{m}");
}

Tipik hata ve düzeltmesi

En sık görülen ihlal: bir okuyucu hâlâ canlıyken yazmaya kalkmak. Aşağıda hata ve iki düzeltme yolu:

main.rs
fn main() {
    let mut v = vec![1, 2, 3];

    let ilk = &v[0];     // paylaşımlı borrow, ilk hâlâ canlı
    v.push(4);           // HATA[E0502]: v'yi &mut almaya çalışır; ilk borrow aktif
    println!("{ilk}");   // ilk'in kullanımı borrow'u canlı tutuyor
}

// DÜZELTME: ilk'i push'tan ÖNCE kullanıp bitir (NLL),
// ya da değeri kopyala: let ilk = v[0]; (i32 Copy).
DİKKAT

v.push(4)'ün tehlikesi teorik değil: Vec büyürken heap'i yeniden tahsis edip taşıyabilir; o anda ilk dangling pointer olurdu. İşte borrow checker'ın engellediği tam C/C++ hatası — iterator/pointer invalidation.

Bu bölümde

  • Tek invariant: aliasing XOR mutation — ya çok &T, ya tek &mut T.
  • NLL ile bir borrow son kullanımında biter, blok sonunda değil — kod daha esnek.
  • En sık hata: canlı bir &T varken &mut almak (E0502).
  • Bu kural iterator/pointer invalidation gibi gerçek C/C++ hatalarını statik olarak engeller.

08 Slice'lar — &[T] ve &str

Slice, sahiplik almadan bir koleksiyonun bitişik bir parçasına açılan ödünç pencere — ptr + uzunluktan ibaret.

Bir slice (dilim), bir koleksiyonun bitişik (contiguous) bir aralığına ödünç verilmiş görünümdür. Sahiplik almaz; içinde sadece bir pointer ve bir uzunluk taşır (fat pointer). C'deki "pointer + length" idiomunun tip-güvenli, sınır-takipli halidir. İki temel slice tipi vardır:

&strString veya string literal üzerine UTF-8 dilim görünümü.
&[T]Vec<T> veya dizi üzerine eleman dilimi görünümü.
main.rs
fn main() {
    let s = String::from("merhaba dünya");
    let ilk: &str = &s[0..7];   // "merhaba" — sahiplik yok, ödünç

    let v = vec![10, 20, 30, 40];
    let orta: &[i32] = &v[1..3]; // [20, 30]

    println!("{ilk} / {orta:?}");
}

Parametre tipi: neden &str ve &[T]?

Bir fonksiyon parametresinde &String yerine &str, &Vec<T> yerine &[T] almak en iyi pratiktir. Sebep: slice daha geneldir. &str alan bir fonksiyon hem String (deref ile) hem string literal hem alt-dilim kabul eder; tek bir imza her kaynağa uyar.

main.rs
// İYİ: &str daha esnek — String, literal, dilim hepsi geçer.
fn ilk_kelime(s: &str) -> &str {
    match s.find(' ') {
        Some(i) => &s[..i],
        None    => s,
    }
}

fn main() {
    let sahip = String::from("merhaba dünya");
    println!("{}", ilk_kelime(&sahip));     // String -> &str (deref coercion)
    println!("{}", ilk_kelime("selam ck"));  // literal zaten &str
}
NOT

ilk_kelime'nin dönüşü girdiyi ödünç alır; derleyici lifetime ilişkisini otomatik çıkarır. Bu yüzden döndürülen &str, kaynak String hayatta olduğu sürece geçerlidir — kaynağı drop edersen slice'ı kullanmak derlenmez. Dangling slice imkânsızdır.

Bu bölümde

  • Slice = sahiplik almayan, ptr+len taşıyan ödünç görünüm; sınır-takipli C "ptr+length".
  • &str String/literal üzerine, &[T] Vec/dizi üzerine dilimdir.
  • Parametrede &str/&[T] tercih et — deref coercion sayesinde daha çok kaynağa uyar.
  • Slice kaynağına bağlı yaşar; kaynak ölünce slice kullanımı derlenmez (dangling yok).

09 Drop, RAII ve sık hatalar

Drop trait'i Rust'ın RAII'sidir — C++ destructor'ının birebir karşılığı, ama move sayesinde double-drop garantili imkânsız.

Bir tip scope'tan çıkarken kaynak bırakması gerekiyorsa Drop trait'ini implement eder. Bu, C++ destructor'ının doğrudan karşılığıdır: dosya kapatma, soket bırakma, kilit çözme gibi temizlikler burada yapılır. String, Vec, File, MutexGuard hepsinin bir Drop'u vardır ve derleyici çağrıyı scope sonuna otomatik yerleştirir.

main.rs
struct Kaynak {
    ad: String,
}

impl Drop for Kaynak {
    fn drop(&mut self) {       // C++ ~Kaynak() gibi
        println!("bırakılıyor: {}", self.ad);
    }
}

fn main() {
    let _a = Kaynak { ad: String::from("A") };
    {
        let _b = Kaynak { ad: String::from("B") };
    } // -> "bırakılıyor: B"  (ters sırada, B önce)
} // -> "bırakılıyor: A"

C++'ta unique_ptr taşındığında kaynak nesne null'a set edilir ki yıkıcı iki kez free yapmasın. Rust'ta bu davranış dile gömülüdür: bir değer move edildiğinde derleyici eski sahibin drop'unu çalıştırmaz; yalnızca son geçerli sahip drop edilir. Böylece double-drop tasarımdan imkânsızdır — programcı disiplinine değil, sahiplik kurallarına dayanır.

KavramC++Rust
Otomatik temizlikdestructor (~T())Drop::drop
Akıllı pointerunique_ptr<T>Box<T>
Move sonrası double-freeelle null'lamaya bağlıdilce imkânsız
Erken bırakmascope/blok hilesidrop(x) fonksiyonu

En sık 3 borrow checker hatası — oku ve çöz

E0382"borrow of moved value" — değeri move ettin, sonra kullandın. Çözüm: .clone() ya da baştan borrow (&) ver.
E0499"cannot borrow as mutable more than once" — iki aktif &mut. Çözüm: borrow'ları zamanda ayır (NLL), kapsamı daralt.
E0502"cannot borrow as mutable ... already borrowed as immutable" — okuyucu canlıyken yazmaya çalıştın. Çözüm: okuyucuyu önce bitir veya değeri kopyala.
NOT

Rust derleyici hata mesajları olağanüstü açıklayıcıdır: hatanın yerini, borrow'un nerede başlayıp nerede çakıştığını ve çoğu zaman somut bir düzeltme önerisini gösterir. Hata kodunu (E0502 gibi) rustc --explain E0502 ile detaylı okuyabilirsin.

Bu bölümde

  • Drop = Rust'ın RAII'si; derleyici drop çağrısını scope sonuna ters sırayla yerleştirir.
  • Move edilen değerin eski sahibi drop edilmez; double-free/double-drop dilce imkânsızdır.
  • Box<T>unique_ptr, erken bırakma için drop(x) kullanılır.
  • En sık hatalar E0382/E0499/E0502; mesajlar açıklayıcıdır, rustc --explain ile derinleşir.