C# Pointer'lar: Unsafe, stackalloc ve fixed kavramları

C Pointer lar Unsafe stackalloc ve fixed kavramları

C# çoğunlukla güvenli (type-safe) bir dil olarak bilinir. Ancak bazı senaryolarda geliştiricilerin doğrudan bellek üzerinde işlem yapması gerekebilir.

C# çoğunlukla güvenli (type-safe) bir dil olarak bilinir. Ancak bazı senaryolarda geliştiricilerin doğrudan bellek üzerinde işlem yapması gerekebilir. Bu noktada unsafe kod, pointer kullanımı, stackalloc ve fixed gibi düşük seviye özellikler devreye girer.

Bu makalede pointer’ların ne olduğunu, unsafe kodun nasıl çalıştığını, stackalloc ile stack üzerinde bellek tahsisini ve fixed anahtar sözcüğünün neden kritik olduğunu detaylı şekilde inceleyeceğiz.

Unsafe Kod Nedir?

C# normalde bellek erişimini tamamen CLR’ın kontrolüne bırakır. Ancak unsafe bağlamı, geliştiricinin doğrudan bellek adresleriyle çalışmasına izin verir. Bu modda:

  • Pointer tanımlayabilirsiniz
  • Pointer aritmetiği yapabilirsiniz
  • stackalloc ile stack üzerinde bellek ayırabilirsiniz
  • fixed ile GC’nin nesneyi taşımamasını sağlayabilirsiniz

Temel kullanım şöyledir:

unsafe
{
    int x = 10;
    int* p = &x;
    Console.WriteLine(*p);
}

stackalloc: Stack Üzerinde Bellek Tahsisi

Normalde C#’ta bellek tahsisi heap üzerinde yapılır ve GC tarafından yönetilir. Ancak bazı durumlarda çok hızlı, geçici ve küçük bellek bloklarına ihtiyaç duyabilirsiniz. İşte stackalloc tam bu noktada devreye girer.

stackalloc, C dilindeki alloca() fonksiyonuna benzer şekilde stack üzerinde bellek ayırır. Bu bellek GC tarafından yönetilmez ve blok sona erdiğinde otomatik olarak temizlenir.

stackalloc Örneği

unsafe
{
    int* buffer = stackalloc int[5];

    for (int i = 0; i < 5; i++)
        buffer[i] = i * 10;

    for (int i = 0; i < 5; i++)
        Console.WriteLine(buffer[i]);
}

Bu örnekte 5 elemanlık bir integer dizisi stack üzerinde oluşturulur. Bu yöntem özellikle:

  • Yüksek performans gerektiren
  • Kısa ömürlü
  • Küçük boyutlu

veri blokları için idealdir.

fixed: Belleğin GC Tarafından Taşınmasını Engellemek

C#’ta nesneler heap üzerinde saklanır ve GC tarafından taşınabilir. Bu durum pointer ile çalışırken sorun yaratır çünkü pointer’ın işaret ettiği adres GC tarafından taşınabilir.

fixed anahtar sözcüğü, GC’nin nesneyi taşımamasını sağlar ve pointer’ın güvenli şekilde kullanılmasına izin verir.

fixed Kullanım Örneği

int[] arr = { 1, 2, 3, 4, 5 };

unsafe
{
    fixed (int* p = arr)
    {
        for (int i = 0; i < arr.Length; i++)
            Console.WriteLine(*(p + i));
    }
}

fixed bloğu sona erdiğinde GC nesneyi tekrar taşımaya başlayabilir.

Pointer Aritmetiği

Pointer aritmetiği, pointer’ın işaret ettiği adres üzerinde matematiksel işlemler yapmanıza olanak tanır.

unsafe
{
    int x = 100;
    int* p = &x;

    Console.WriteLine(*(p));     // 100
    Console.WriteLine(*(p + 0)); // 100
}

Dizilerle birlikte kullanıldığında oldukça güçlüdür ancak yanlış kullanıldığında ciddi hatalara yol açabilir.

Unsafe Kod Ne Zaman Kullanılmalı?

Aşağıdaki durumlarda unsafe kod mantıklıdır:

  • Performans kritik algoritmalar
  • Interop (C/C++ kütüphaneleri ile çalışma)
  • Özel bellek yönetimi gerektiren senaryolar
  • Span/Memory gibi modern yapılarla düşük seviye optimizasyon

Ancak çoğu durumda C#’ın güvenli yapıları (Span<T>, Memory<T>, ArrayPool vb.) yeterlidir.

Sonuç

Pointer, unsafe, stackalloc ve fixed gibi özellikler C#’ın düşük seviyeli programlama gücünü ortaya çıkarır. Doğru kullanıldığında performans kazandırır, ancak yanlış kullanıldığında güvenlik açıklarına ve bellek hatalarına yol açabilir.

Bu nedenle bu özellikler yalnızca gerçekten ihtiyaç duyulan durumlarda kullanılmalı ve her zaman dikkatli olunmalıdır.