Bellek sızıntısı (memory leak): tanım, nedenler ve bulma yöntemi
Sözlük

Bellek sızıntısı (memory leak): tanım, nedenler ve bulma yöntemi

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 4 dk okuma

Memory leak, yani bellek sızıntısı nedir, yazılımda nasıl oluşur, hangi belirtilerle fark edilir ve profilleme ile nasıl bulunup giderilir, örnekle anlatılır.

Bellek sızıntısı nedir?

Bellek sızıntısı (memory leak), bir programın artık ihtiyaç duymadığı belleği sisteme geri vermemesi ve bu yüzden kullanılan bellek miktarının zamanla basamak basamak büyümesidir. Program çalıştıkça tüketim yükselir; sonunda süreç yavaşlar, işletim sistemi tarafından sonlandırılır ya da bellek yetersizliği hatasıyla çöker.

Sızıntı, programın bir anda çok bellek istemesinden farklıdır. Büyük bir veri kümesini yüklemek yüksek ama kararlı bir kullanım yaratır. Sızıntıda ise iş yükü sabit kaldığı halde kullanım düşmeden tırmanır. Ayırt edici işaret, yoğun saat geçtikten sonra bile belleğin eski seviyesine inmemesidir.

Bellek sızıntısı nasıl oluşur?

C ve C++ gibi belleği elle yönetilen dillerde sızıntı çoğunlukla ayrılan alanın serbest bırakılmamasıdır: program bellek ister, işi bitince geri vermeyi unutur ve o alana erişen son işaretçi de kaybolur.

Java, JavaScript, Python ve C# gibi çöp toplayıcılı dillerde durum daha az bilinen bir biçim alır. Çöp toplayıcı kullanılmayan nesneyi değil, erişilemeyen nesneyi temizler. Bir nesneye hâlâ bir yerden başvuru varsa, kodun onu bir daha kullanmayacağı çöp toplayıcı tarafından bilinemez ve nesne bellekte kalır. Bu tür sızıntıya mantıksal sızıntı denir ve çöp toplayıcılı dillerde görülen sızıntıların büyük bölümü bu kategoridedir.

Bu yüzden çöp toplayıcı olması sızıntıyı imkânsız kılmaz; yalnızca sorunun yerini değiştirir. Soru artık bellek geri verildi mi sorusu değil, bu nesneye kim hâlâ başvuruyor sorusudur.

Sık görülen nedenler

Sızıntıların çoğu birkaç tekrarlayan kalıba dayanır:

  • Sınırsız büyüyen koleksiyonlar: statik bir liste ya da harita her istekte büyür ama hiç temizlenmez.
  • Kaldırılmayan olay dinleyicileri ve geri çağırmalar: bir ekran ya da bileşen kapanır, fakat kaydettiği dinleyici nesneyi canlı tutmaya devam eder.
  • Kapatılmayan kaynaklar: dosya, ağ bağlantısı, veritabanı bağlantısı ve akışlar kapatılmadığında hem bellek hem sistem kaynağı tükenir.
  • Uzun ömürlü nesnenin kısa ömürlü nesneyi tutması: statik alanlar, tekil nesneler ve iş parçacığı yerel değişkenleri kendinden kısa yaşaması gereken nesnelere başvuru taşıyabilir.
  • Sınırı ve süresi olmayan önbellek: sonuçları bellekte saklayan ama hiçbir şeyi atmayan bir yapı zamanla kendi başına sızıntıya dönüşür.

Son madde önbellek tasarımıyla doğrudan ilgilidir. Önbelleğe bir üst boyut sınırı, bir geçerlilik süresi ve doluluk halinde hangi kaydın atılacağını belirleyen bir tahliye politikası verilmezse, önbellek bellek sızıntısından ayırt edilemez hale gelir.

Küçük bir örnek

Örneğin bir web servisi, giriş yapan her kullanıcının bilgisini hızlı erişim için statik bir haritada saklıyor olsun. Kod kullanıcıyı haritaya ekliyor ama oturum bitince çıkarmıyor. Test ortamında sorun görünmez, çünkü az sayıda kullanıcı vardır ve servis sık yeniden başlatılır.

Üretimde servis haftalarca çalışır, harita her yeni kullanıcıyla büyür ve kayıtlar hiç silinmez. Bellek kullanımı grafiği düzgün bir yokuş çizer. Çöp toplayıcı sık çalışmaya başlar ama bu kayıtlara hâlâ başvuru olduğu için hiçbirini silemez. Sonunda servis bellek yetersizliği hatası verir ve yeniden başlatılana kadar yanıt vermez.

Çözüm, oturum bittiğinde kaydı haritadan kaldırmak ya da haritayı boyut sınırı ve geçerlilik süresi olan bir önbellek yapısıyla değiştirmektir.

Nasıl tespit edilir ve giderilir?

Tipik belirtiler şunlardır: bellek grafiğinin testere dişi yerine merdiven biçiminde yükselmesi, çöp toplama etkinliğinin giderek sıklaşması, yanıt sürelerinin uzaması ve servisin yeniden başlatılınca düzelip bir süre sonra aynı hâle dönmesi.

Bulma süreci genel olarak şu adımları izler:

  • Bellek kullanımını zaman içinde izleyin ve artışın hangi iş yüküyle ilişkili olduğunu belirleyin.
  • Bir profilleyici ya da bellek dökümü aracıyla, sorun gelişirken farklı zamanlarda bellek anlık görüntüsü alın.
  • Anlık görüntüleri karşılaştırın: hangi nesne türünün sayısı sürekli artıyor?
  • Artan nesnelere kimin başvurduğunu izleyin. Bu başvuru zinciri sızıntının kaynağını gösterir.
  • Düzeltmeyi yapın ve aynı yük senaryosunu yeniden çalıştırarak eğrinin düzleştiğini doğrulayın.

Önlem olarak kaynakları otomatik kapatan kalıplar kullanın, koleksiyonlara ve önbelleklere sınır koyun, dinleyici kaydı yapılan her yerde kaydı silen karşılığı da yazın. Kod incelemesinde statik alanlara dikkat etmek de aynı yatırımdır.

Benzer kavramlardan farkı

Yüksek bellek kullanımı: Program gerçekten çok veriyle çalışıyordur ve kullanım kararlıdır. Sızıntıda aynı iş yükü altında kullanım sürekli artar.

Bellek parçalanması: Toplam boş bellek yeterlidir ama bitişik büyük blok bulunamaz. Burada bellek kaybolmaz, bölünür.

Yığın taşması (stack overflow): Genellikle aşırı derin çağrı zincirinden doğar ve hızlı, ani bir çöküştür. Sızıntı ise yavaş ve birikimlidir.

Çöp toplama: Sızıntıyı önleyen bir mekanizma değil, erişilemeyen nesneleri temizleyen bir mekanizmadır. Başvurusu süren nesneyi toplayamaz.

Önbellekleme: Bilerek bellekte veri tutmaktır. Sınırsız ve kontrolsüz bırakıldığında sızıntıya dönüşür.

Mindset programlarında nerede çalışılır?

Bellek sızıntısı, yazılım ve altyapı ekiplerinde üretimde yaşanan kesinti ve yavaşlama sorunlarının gündelik nedenlerinden biridir. Java İleri Seviye: JVM Performans ve Bellek Yönetimi programı, JVM bellek bölgelerini, çöp toplama algoritmalarını ve profilleme ile gözlemlenebilirliği ayrı modüllerde ele alır; backend geliştiriciler ve sistem güvenilirliği ile ilgilenen ekipler için sızıntıyı sezgiyle değil ölçümle teşhis etme alışkanlığı kazandırmayı hedefler.

Redis ile Önbellekleme ve Veri Yapıları programındaki bellek yönetimi ve kalıcılık modülü ise önbelleğin sınırsız büyümesi sorununa tasarım tarafından yaklaşır.

İlgili Mindset programı

Java İleri Seviye: JVM Performans ve Bellek Yönetimi

Sık sorulanlar

Sık sorulan sorular

Çöp toplayıcısı olan dillerde bellek sızıntısı olur mu?

Evet. Çöp toplayıcı yalnızca hiçbir yerden erişilemeyen nesneleri temizler. Bir liste, harita ya da dinleyici kaydı nesneye başvuru tuttuğu sürece nesne canlı sayılır ve silinmez. Bu yüzden Java, JavaScript, Python ve C# gibi dillerde de sızıntı görülür, yalnızca nedeni genelde unutulmuş bir başvurudur.

Bellek sızıntısını yeniden başlatma çözer mi?

Yeniden başlatma yalnızca belirtiyi geçici olarak siler, çünkü süreç temiz bellekle başlar. Neden kodda durduğu için kullanım yeniden yükselmeye başlar. Acil önlem olarak yeniden başlatma kullanılabilir, ama kalıcı çözüm sızıntının kaynağını profilleme ile bulup düzeltmektir.

Bellek sızıntısı güvenlik sorunu yaratır mı?

Doğrudan bir açık olmayabilir, ancak bellek tükenmesi hizmeti durdurabileceği için erişilebilirlik riski doğurur. Sızıntıyı tetikleyen bir istek türü bilinirse, kötü niyetli biri bunu tekrar tekrar göndererek hizmeti yavaşlatabilir. Bu nedenle sızıntılar güvenilirlik kadar güvenlik açısından da ciddiye alınır.

Mobil uygulamalarda da bellek sızıntısı olur mu?

Olur. Ekran kapandıktan sonra bellekte kalan görünümler, kaldırılmayan dinleyiciler ve ağ geri çağırmaları yaygın nedenlerdir. Mobil cihazın belleği sınırlı olduğundan sızıntı kullanıcıya uygulamanın yavaşlaması ya da işletim sistemince kapatılması olarak yansır.

Bellek Sızıntısı (Memory Leak) Nedir? Nedenleri ve Tespiti