---
title: '`unsafe` Rust'
source: 'https://academia.sh/tr/kurslar/rust-ileri/unsafe-rust'
course: 'Rust Ekosistemi ve İleri Konular'
language: tr
updated: '2026-09-13T05:09:27+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'unsafe bloğun derleyicinin denetimini toptan değil, yalnız belirli birkaç işlem için kapattığını aynı blok içinde koşturarak gösterir'
    - 'Ham işaretçi okuma, sınır denetimsiz erişim ve sözleşmeli bir işlevin üçünün de güvenli karşılığıyla aynı sonucu verdiğini karşılaştırarak kanıtlar'
    - 'Devredilen bir güvencenin doğru kullanıldığında sonuçta görünmez kaldığını, yanlış kullanımın sorumluluğunu kimin taşıdığını ayırt ederek açıklar'
---

# `unsafe` Rust

unsafe bloğunun derleyicinin bütün denetimini değil, yalnız birkaç belirli işlemi kapsayan denetimini kapattığı; aynı blok içinde bir ham işaretçi okumasının denetimsiz kaldığı ama bir dilim sorgusunun hâlâ denetlendiği koşturularak gösterilir.

Önceki konu, bir makronun ürettiği gövdenin biçimi ne kadar farklı görünürse görünsün
yine sıradan kaynak gibi tip denetiminden geçtiğini gösterdi: derleyici üretilen bir
işlevi de, elle yazılmış bir işlev kadar sıkı denetledi. Bu konu aynı soruyu ters yönden
sorar: derleyicinin bu denetimi hiç yapmadığı, yapmayı bırakıp yazan tarafa bıraktığı bir
yazım var mıdır? Yanıt `unsafe` anahtar sözcüğüdür — ama bu dersin bulgusu, o sözcüğün
göründüğü kadar geniş bir kapı açmadığıdır.

Ödünç Denetleyicisi dersi (M10/K02) derleyicinin sahiplik ve ödünç kurallarını nasıl
sınadığını, hangi yazımları reddettiğini kurdu. Bu ders o denetleyicinin **kapandığını**
göstermez — kapanmadığını, yalnızca birkaç işlemin önündeki engelin kaldırıldığını
gösterir. Standart Kütüphane ve Akışlar dersi (M08/K03) bir davranışın garantisini kimin
verdiğini sormuştu: arayüz mü, gerçekleştirim mi, çağıran mı — bir sözleşmenin tarafları.
Bu derste sorulan farklıdır: derleyicinin kendi denetiminin, sözleşmenin hiçbir tarafına
bakmaksızın, nerede durduğu.

Bu kapının var olmasının bir nedeni var: ödünç denetleyicisinin sınadığı kurallar,
gerçekleştirilebilecek her doğru programı kapsamıyor. Bir dairesel tampon, bir düğüm
havuzu ya da bir donanım kaydına doğrudan erişen bir sürücü gibi düzenekler, ödünç
denetleyicisinin izleyebileceğinden daha karmaşık bir sahiplik örüntüsü taşıyabilir —
denetleyici bu örüntüyü doğru bulsa bile reddedebilir, çünkü sınama kuralı örüntünün
kendisinden değil, denetleyicinin izleyebildiği örüntü sınıfından gelir. `unsafe`, bu
uyuşmazlığı kapatan bir kaçış menfezidir: yazan taraf, denetleyicinin sınayamadığı bir
gerekçeyle "bu doğru" diyebilir. Standart kütüphanenin kendi büyüyen dizi ve dilim
tipleri de böyle kurulmuştur — dışarıdan bakan koda güvenli bir arayüz sunarlarken,
kendi gövdelerinde aynı ham işaretçi işlemlerini kullanırlar. Bu ders o gövdelerin
içine bakmaz; yalnızca aynı iznin sıradan bir programda nasıl çalıştığını ölçer.

## `unsafe` Bloğunun Sınırlı İzni

Bir ham işaretçi kurmak `unsafe` gerektirmez. `&deger as *const i32` yazımı sıradan bir
ifadedir, derlenir ve hiçbir denetimi atlamaz — kurulan şey yalnız bir adrestir, henüz
okunmamıştır. Ödünç kuralları da bu satırda devrede değildir, çünkü ham işaretçiler ödünç
denetleyicisinin izlediği tipler arasında yer almaz; onlar için sahiplik, yaşam süresi ve
tekillik gibi bir muhasebe tutulmaz.

Kısıt, işaretçiyi **okumaya** çalışıldığında başlar. Bir ham işaretçinin gösterdiği yerde
gerçekten geçerli bir değer olduğunu derleyici bilemez — işaretçi boş olabilir, ait olduğu
bellek geri verilmiş olabilir, ya da yalnızca uydurma bir adres taşıyor olabilir. Derleyici
bu üç olasılığı ayırt edemediği için, okuma işlemini `unsafe` bloğunun içine almayı zorunlu
kılar: kod derlenir, ama "burada bir sözleşme var ve onu ben karşılıyorum" beyanı yazan
tarafa aittir. Aynı kısıt, gövdesi `unsafe` işaretli bir işlevi çağırmak için de geçerlidir
— işlevin adı, çağıranın bir ön koşulu sağlaması gerektiğini söyler, ama bu koşulu
derleyici sınamaz.

Bu izin listesi kısadır ve dilin kendisi tarafından sabitlenmiştir: derleyici hangi
işlemlerin `unsafe` gerektirdiğini kaynaktan okur, çağıranın niyetinden değil. Aşağıdaki
koşum, `unsafe` gerektirmeyen üç işlemi yan yana koyuyor: bir ham işaretçi kurmak, onu
taşmaya karşı tanımlı bir biçimde kaydırmak ve iki işaretçiyi birbiriyle karşılaştırmak.
Üçü de değeri **okumadığı** için, geçersiz bir adresle çalışıyor olsalar bile hiçbir şeyi
bozmazlar — bozacak olan, o adresteki veriye erişmeye kalkmaktır.

```rust
// izin.rs — hangi isaretci islemleri unsafe gerektirmiyor
fn main() {
    let v = vec![10, 20, 30, 40];
    let isaretci = v.as_ptr();                    // kurma
    let kaydirilmis = isaretci.wrapping_add(1);    // tasmaya karsi tanimli kaydirma
    let kendiyle_esit = isaretci == isaretci;
    let kaydirilmisla_esit = isaretci == kaydirilmis;

    println!("kendiyle esit mi: {}", kendiyle_esit);
    println!("kaydirilmisla esit mi: {}", kaydirilmisla_esit);
}
```

```
kendiyle esit mi: true
kaydirilmisla esit mi: false
```

Bu üç işlemin ortak yanı, sonuçlarının kendi başlarına hiçbir belleği açığa çıkarmamasıdır:
bir adresin kendisiyle eşit olup olmadığını bilmek, o adresteki değeri bilmekten farklıdır.
**DS1.** `wrapping_add` çağrısı burada bilinçli seçildi — dilin bu adı taşıyan işaretçi
yöntemi, kaydırma sonucu bir taşmaya uğrasa bile tanımlı bir değer döndürür ve bu yüzden
`unsafe` istemez; buna karşılık aynı kaydırmayı yapan `add` yöntemi, sonucun aynı ayrılmış
bellek bloğunun içinde ya da bir bayt ötesinde kalmasını çağırandan **ön koşul** olarak
ister ve bu ön koşul derleyici tarafından sınanmadığı için çağrısı `unsafe` gerektirir. İki
yöntem aynı aritmetiği yapar; aralarındaki fark, taşma durumunda neyin garanti edildiğidir.

Buna karşılık bir ham işaretçiyi **okumak** ya da **yazmak** ve gövdesi `unsafe` işaretli
bir işlevi çağırmak `unsafe` bloğu ister — çünkü bu işlemlerin ikisi de, derleyicinin
sınayamadığı bir varsayıma (adresin geçerli olduğuna, işlevin ön koşulunun sağlandığına)
dayanır. Aşağıdaki iki bölüm bu ayrımı aynı blok içinde koşturarak gösteriyor.

## Aynı Blok İçinde Süren ve Duran Denetim

Bir `unsafe` bloğu, içine yazılan her satırı aynı ölçüde etkilemez. Aşağıdaki koşum aynı
blok içine iki farklı işlem koyuyor: biri bir ham işaretçiden doğrudan okuma, öteki bir
dilim üzerinde sınır denetimli bir sorgu. İkisi de aynı `unsafe` anahtar sözcüğünün altında
duruyor, ama yalnız biri denetimden muaf.

**DS2.** Dört elemanlı bir tam sayı dilimi kullanılıyor ve sorgulanan indis (onuncu öge)
bu dilimin sınırlarının dışında.

```rust
// blokA.rs — ayni unsafe blok icinde suren ve duran denetim
fn main() {
    let v = vec![10, 20, 30, 40];
    let isaretci = v.as_ptr();

    // Ayni blokta iki islem: biri ham isaretci uzerinden okuyor (denetimsiz),
    // digeri guvenli dilim sorgusu (v.get) yapiyor (hala denetimli).
    let (ilk_ham, onuncu) = unsafe { (*isaretci, v.get(10)) };

    println!("ham okuma: {}", ilk_ham);
    println!("onuncu oge: {:?}", onuncu);
}
```

```
ham okuma: 10
onuncu oge: None
```

İki satır da aynı `unsafe` bloğunun içinde çalıştı, ama farklı yollardan geçti. `*isaretci`
ham işaretçiyi doğrudan okudu — burada hiçbir sınır kontrolü yoktur, adres ne gösteriyorsa
o okunur. `v.get(10)` ise dilimin kendi yönteminden geçti; bu yöntemin gövdesi `unsafe`
işaretli değildir ve içindeki sınır denetimi hâlâ çalışıyor, bu yüzden dördüncü elemandan
sonrasını istediğinde çökmek yerine `None` döndü. **DS3.** `unsafe` bloğu burada yalnızca
`*isaretci` satırının önündeki engeli kaldırdı; `v.get` çağrısı zaten güvenli bir yöntemdi
ve `unsafe` bloğunun içine girmesi onun gövdesindeki denetimi değiştirmedi.

Bu gözlem dersin ana bulgusudur: `unsafe` bir anahtar değildir, derleyicinin bütün
kilitlerini birden açmaz. Blok yalnızca içine yazılan **belirli** işlemler için izin verir
— o işlemlerin dışındaki her şey, blok içinde bile, kendi kurallarına tabi kalır. Ödünç
denetleyicisi burada da devrede: `v`'nin sahipliği, `isaretci`nin ondan türetilmiş olması,
her ikisinin kapsam kuralları — hiçbiri `unsafe` bloğu yüzünden askıya alınmadı. Askıya
alınan tek şey, ham işaretçi okumasının kendi sınır denetimiydi.

Yukarıdaki koşum, güvenli çağrıyı `unsafe` bloğunun **içine** koyarak bunu bilerek gösterdi;
sıradan bir yazımda böyle bir zorunluluk yoktur, `v.get(10)` kendi başına bir `unsafe`
bloğu gerektirmez. Yaygın alışkanlık, bir `unsafe` bloğunu yalnız gerçekten gerektiren
satırlarla sınırlı tutmaktır — blok ne kadar genişlerse, hangi satırın hangi sözleşmeye
dayandığını sonradan ayırt etmek o kadar zorlaşır. Bu derste iki işlemin aynı blokta
yazılması, bu alışkanlığın neden var olduğunu somutlaştırmak için: blok geniş tutulduğunda
bile denetimin nerede sürdüğü, nerede durduğu kaynaktan okunabiliyor, ama bu okunabilirlik
otomatik değil, satır satır izlemeyi gerektiriyor.

## Devredilen Üç İşlem

Önceki bölümdeki `*isaretci` okuması gibi, denetimin devredildiği satırlar tek başlarına
durmaz — her biri, aynı işi yapan güvenli bir karşılıkla yan yana konabilir. Aşağıdaki
koşum üç ayrı devredilmiş işlemi güvenli karşılıklarıyla karşılaştırıyor: ham işaretçi
aritmetiğiyle okuma, dilimin denetimsiz erişim yöntemi ve bir sözleşmeyi taşıyan `unsafe`
işlevin çağrısı.

Bu üç yazımın işlevi aynı olsa da kullanım yerleri farklıdır. Ham işaretçi aritmetiği,
bir bellek bloğunu Rust'ın kendi dilim tipinden bağımsız olarak dolaşmak gerektiğinde
kullanılır — örneğin bir yabancı işlevden dönen bir bellek bölgesini okurken, ki bu
konu bir sonraki derste ele alınıyor. `get_unchecked`, bir dilim üzerinde çalışırken
indisin geçerliliği zaten başka bir yerde (bir döngü sınırıyla, bir arama sonucuyla)
kanıtlanmışsa kullanılır. Sözleşmeli bir `unsafe` işlev ise bu iki yazımı bir arada
paketleyip, çağıran tarafa yalnızca imzayı okumasının yeterli olduğu bir arayüz sunmak
için kullanılır — sözleşme hâlâ vardır, ama gövde başka bir dosyaya taşınabilir.

**DS4.** Karşılaştırılan dilim yine `[10, 20, 30, 40]`; ham işaretçi ikinci indisten
başlayıp iki konum kaydırılıyor, denetimsiz erişim doğrudan ikinci indise gidiyor.

```rust
// blokB.rs — devredilen uc islem ve guvenli karsiliklari
unsafe fn ikinci_ogeyi_al(v: &[i32]) -> i32 {
    // Sozlesme: cagiran, v'nin en az iki oge tasidigini garanti eder.
    *v.get_unchecked(1)
}

fn main() {
    let v = vec![10, 20, 30, 40];
    let isaretci = v.as_ptr();

    let ham = unsafe { *isaretci.add(2) };
    let denetimsiz = unsafe { *v.get_unchecked(1) };
    let sozlesmeli = unsafe { ikinci_ogeyi_al(&v) };

    println!("ham isaretci okuma: {} (guvenli karsiligi {})", ham, v[2]);
    println!("denetimsiz erisim: {} (guvenli karsiligi {})", denetimsiz, v[1]);
    println!("sozlesmesi devredilen islev: {} (guvenli karsiligi {})", sozlesmeli, v[1]);
}
```

```
ham isaretci okuma: 30 (guvenli karsiligi 30)
denetimsiz erisim: 20 (guvenli karsiligi 20)
sozlesmesi devredilen islev: 20 (guvenli karsiligi 20)
```

Üç satırın da sonucu, `[]` ile yapılan sınır denetimli erişimle birebir aynı. Bu bir
rastlantı değil: `add(2)` ile ilerletilen işaretçi de, `get_unchecked(1)` çağrısı da,
`ikinci_ogeyi_al` işlevinin içindeki çağrı da, dilimin bellekteki düzenini doğru
okuyor — yalnızca bu doğruluğu kimin garanti ettiği değişiyor. Güvenli `[]` erişiminde
garantiyi dilimin kendi yöntemi verir ve indis sınırın dışındaysa çalışma anında panikle
durur. `get_unchecked` ve ham işaretçi aritmetiğinde bu garantiyi kimse vermez; doğru
indisi seçmek çağıranın yükümlülüğüdür.

`ikinci_ogeyi_al` işlevi bu yükümlülüğü kaynakta görünür kılan bir yazım göstermek için
var: imzasının önündeki `unsafe` sözcüğü, gövdenin çağrılmadan önce bir ön koşulun
sağlanmış olmasını beklediğini söyler. Bu, dilin kendisinin tanıdığı bir yazım kalıbıdır —
işlevin adı ve imzası, gövdesindeki denetimsiz erişimi çağıranın gözünden gizlemez, tersine
işaretler. Bir işlevi `unsafe` işaretlemek, gövdesinin içindeki her satırı otomatik olarak
denetimsiz kılmaz da: gövde içinde de yalnız gerçekten `unsafe` gerektiren satırlar
(burada `get_unchecked` çağrısı) o statüyü taşır, geri kalanı sıradan denetimli koddur. **DS5.** İşlevi `unsafe` çağıran taraf, `v`'nin en az iki eleman taşıdığını
kendisi doğrulamak zorunda; bu koşum sırasında dilim dört eleman taşıdığı için sözleşme
karşılandı ve sonuç güvenli karşılığıyla eşleşti.

Bu üç yöntemin dilde bulunmasının bir gerekçesi var: güvenli `[]` erişimi her çağrıda bir
sınır denetimi **adımı** yapar — indisin dilimin uzunluğundan küçük olup olmadığını
sınar, sonra okur. `get_unchecked` bu adımı atlar; okuduğu tek şey, çağıranın zaten
başka bir yerde doğruladığı bir indistir. Bu ders o adım farkını saymıyor, çünkü koşum
tek bir erişimle sınırlı ve süre bu müfredatta hiçbir yerde ölçülmüyor; önemli olan,
atlanan adımın **hangi denetim olduğunun** kaynaktan okunabilir olmasıdır — `get_unchecked`
adı, sınır denetiminin atlandığını doğrudan söyler, gizlemez.

## Sınırlayıcı Ölçüm

Bu üç işlemin ortak özelliği, doğru kullanıldıklarında sonuçta hiçbir iz bırakmamalarıdır.
Yukarıdaki koşumda hem ham okuma hem denetimsiz erişim hem sözleşmeli çağrı, güvenli
karşılıklarıyla aynı sayıyı verdi — bir gözlemci yalnız çıktıya bakarak hangi satırın
`unsafe` olduğunu ayırt edemez. Fark sonuçta değil, **yanlış** kullanıldığında ne olacağının
kimin sorumluluğunda olduğundadır.

Yanlış kullanım bu derste koşturulmuyor, çünkü sınırın dışına taşan bir okuma tanımsız
davranıştır ve sonucu bu makineye, bu koşuma özgüdür — bir sonraki koşumda aynı hatayı
tekrar üretmeyebilir, sessizce yanlış bir değer okuyabilir ya da çöküşe yol açabilir.
Düzyazıyla tarif etmek yeterli: `isaretci.add(100)` çağrısı, dört elemanlık dilimin çok
ötesine geçen bir adresi okumaya çalışırdı. Derleyici bu çağrıyı reddetmez — çünkü reddetmek
için adresin ne gösterdiğini bilmesi gerekirdi ve bilmiyor. Aynı şekilde, `ikinci_ogeyi_al`
işlevi iki elemandan az bir dilimle çağrılsaydı, sözleşme ihlal edilmiş olurdu ve derleyici
bunu da fark etmezdi; imza yalnızca çağıranın bir sözü tuttuğunu varsayar, sözü sınamaz.

Bu, `unsafe` denetiminin ne yaptığını netleştiriyor: derleyici artık "bu doğru mu" diye
sormuyor, yalnızca "bu, kaynakta izin verilmiş bir yazım mı" diye soruyor. Sınırın nerede
durduğunu ölçmek, sınırın ötesinde ne olduğunu koşturmaktan ayrı bir iştir — bu ders
yalnız ilkini yapıyor.

Bu ayrım, `unsafe` işlevlerin neden bir yazım kuralına ihtiyaç duyduğunu da açıklıyor.
`ikinci_ogeyi_al` gibi bir işlevin üstüne, hangi ön koşulun beklendiğini anlatan bir
belge satırı eklemek dilin zorunlu tuttuğu bir şey değildir — ama yaygın bir yazım
alışkanlığıdır, çünkü imzadaki `unsafe` sözcüğü tek başına "hangi" ön koşulu söylemez,
yalnızca "bir" ön koşul olduğunu söyler. Bu koşumdaki işlev bu belgeyi bir satırlık bir
yorumla taşıyor; Belgelendirme dersi ileride bu tür bir belge satırının doğruluğunun da
kendi başına denetlenmediğini, ayrı bir sınıfa (**denetlenmiyor**) düştüğünü gösterecek.
Burada önemli olan, `unsafe`in kendisinin bu belgeyi zorunlu kılmaması, yalnızca dilin
kaynakta görünür bir işaret bırakmasıdır: `unsafe` sözcüğü olmadan bu işlev hiç
çağrılamaz, ama sözcüğün varlığı, çağıranın gerçekten doğru bir dilim geçirdiğini
göstermez.

## Özet

- `unsafe` bloğu derleyicinin bütün denetimini kapatmaz; yalnız birkaç belirli işlemi
  (ham işaretçi okuma/yazma, `unsafe` işlev çağrısı gibi) kapsam dışına alır — aynı
  bloktaki güvenli bir çağrı (`v.get`) hâlâ **sürdürüyor** sınıfında kaldı
- Ham işaretçi aritmetiğiyle okuma, dilimin denetimsiz erişim yöntemi ve sözleşmeli bir
  `unsafe` işlevin çağrısı — üçü de denetimin yazana **devredildi**ği işlemlerdir
- Devredilen üç işlemin üçü de doğru kullanıldığında güvenli karşılığıyla birebir aynı
  sonucu verdi; fark sonuçta değil, yanlış kullanımın sorumluluğunda
- Ödünç denetleyicisi `unsafe` bloğu içinde de çalışmaya devam eder — kapanan bir
  denetleyici değil, yalnızca açılan birkaç işlem söz konusudur
- `unsafe` işaretli bir işlevin imzası, gövdesindeki ön koşulu çağırana görünür kılan bir
  yazım kalıbıdır; derleyici bu ön koşulu sınamaz, yalnız varlığını beyan ettirir

## Sonraki Adım

Bu derste devredilen güvence hep aynı programın içinde kaldı — ham işaretçi de,
denetimsiz erişim de Rust'ın kendi bellek düzenini okuyordu; derleyici, işaretçinin
gösterdiği belleğin hangi tipten olduğunu ve dilimin gerçek uzunluğunu her zaman biliyordu,
yalnız bu bilgiyi okuma anında sınamayı bırakmıştı. Sıradaki ders aynı devri bir adım
öteye taşıyor: gövdesini derleyicinin hiç görmediği, başka bir dille yazılmış bir işlevi
çağırmak. Orada sözleşme yalnız bir ön koşul değil, bir **imza**dır — derleyici artık
karşı tarafın gövdesine hiç bakmadan, yalnız yazılan bildirime güvenerek derler.
