Swift için Memory Leak - I

Kurtuluş Ahmet TEMEL
3 min readMar 2, 2020

--

Selam Arkadaşlar,

Bu yazımızda Swift dili orjininde memory leak kavramının ne olduğunu, bu durumu nasıl ortadan kaldıracağımızdan bahsedeceğim. Yazının ikinci serisinde ise Xcode Memory Graph özelliğinin nasıl kullanıldığına değineceğim.

Memory Leak

Memory Leak’in ne olduğunu anlamak için öncelikle bu kavramın sözlük ve Apple tanımlarına bakalım;

Belleğin referanssız nesneler ile belli bir kısmının sonsuza kadar işgal edilmesi ve bu işgal neticesinde ilgili bellek kısmının kullanılmaması durumuna Memory Leak (bellek sızıntısı) denir.

“Memory that was allocated at some point, but was never released and is no longer referenced by your app. Since there are no references to it, there’s now no way to release it and the memory can’t be used again.”

Her gün geliştirdiğimiz uygulamalarımız zamanla büyüyor ve bir türlü çözüme ulaştıramadığımız Memory Leak problemleriyle tekrar tekrar baş etmemiz gerekebiliyor. Bu problemleri çözmediğimizde ise uygulamamızda beklenmedik yavaşlamalara ve çökmelere neden olabilir. Bu durumun başlıca çözümü nesnelerin işleri bittiğinde (yani referans sayısı 0 olduğunda) hafızadan düzgün bir şekilde temizlemek.

Şimdi gelelim bu sızıntıların nedenlerine ve çözüm için dikkat etmemiz gereken durumlara. Oluşan sızıntıların nedeni olarak retain cycle durumunu en başa yazabiliriz. Objective-C zamanlarındaki MRC (Manual Reference Counting)- ARC(Automatic Reference Counting) dönüşümü ile bu döngüyü yönetmek kısmen kolaylaşmış olsa da aslında biz geliştiricilerinde yapması ve anlaması gereken bazı kavramlar hâlâ var.

Strong, Weak ve Unowned Referans Kavramları

Strong referans tanımını yazdığımız kod içerisinde hemen hemen her yerde bulabilirsiniz. Çünkü strong referans tanımı ARC ile gelen varsayılan referans tanımıdır. Bu referans tanımını doğrusal bir referans akışında kullanıldığında bir soruna yol açmaz. Lakin sınıf örneklerini yazarken sınıflar arasında güçlü bir referans döngüsüne sahip kod yazmak açıkcası sızıntıya zemin hazırlamaktan başka bir şey değildir. Aşağıda yer alan Car ve Owner sınıfları arasında kurulan ve varsayılan olarak referanslandırılan bir örneği inceleyebilirsiniz.

Burada Car sınıfı Owner sınıfını strong referansla ve Owner sınıfı da Car sınıfını strong referansla içinde barındırdığından Retain Cycle durumu gözlenir. Yukarıdaki örnekte de retain cycle durumu olduğu için hem Car hem de Owner objesinin hafızadan yok olması mümkün değildir. Bir objenin hafızadan silinebilmesi için önce tüm referanslarının yok olması gerekmektedir. Ama burada referanslar birbiri içerisinde olduğundan hiçbir zaman hafızadan silinmez.

Weak referans ise strong referans tanımının aksine nesneler arasında güçlü bir bağ kurmayarak referanslarının sıfırlanmasının akabinde hayatlarına son verirler. Burda unutulmaması gereken sabitler güçsüz olarak tanımlanmaz ama değişkenler bu referans tanımını alabilir. Aşağıda yukarda aralarında güçlü bağ kurduğumuz iki sınıfın güncel haline bakabilirsiniz.

Not: Her ikisi weak olarak tanımlamak yerine yalnızca bir zayıf referans kullanmak da sorunu çözerdi ve güçlü referans döngüsünü kırardı.

Unowned referans tanımı ise weak referans tanımına oldukça benzemektedir. weak referansların aksine unowned referanslar için Optinal tanımlama yapılamaz. Unowned referansları yalnızca nesne referansının sıfır olmayacağından emin olduğumuzda kullanmanız önemlidir.

Apple, weak - unowned kullanımı arasındaki seçimi aşağıdaki gibi yapalım istemiştir.

“Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialisation.” Apple Documentation

Bu durumdan çıkarmamız gereken sonuç şudur ki;

ARC uygulamamızda bellek sızıntısı oluşturmanızı engellemez. Doğrusal olmayan strong referanslar ve referans döngüleri, referans sayısının sıfıra ulaşmasını önleyebilir. weak ve unowned referansların kullanılması, bundan kaçınmanıza ve uygulama belleğinizi dengede tutmanıza yardımcı olur.

Closure ve Delegation

Sızıntıya sebep olacak diğer durumlar ise uygulamalarımızda kullandığımız Closure ve Delegation yapılarıdır.

Closure yapıları için durumları yok etmek adına ilgili çağrımlarda bazı noktalara dikkat etmemiz gerekmektedir. Eğer closure’ın, içindeki sakladığı objelerden daha uzun süre yaşamayacağına eminsek unowned anahtar kelimesini kullanabiliriz. Eğer emin değilseniz weak anahtar kelimesini kullanmamız gerekir. Aksi taktirde sızıntıya sebebiyet verebiliriz.

Delegation durumunda ise daha önce örnek verdiğimiz Car, Owner sınıflarındaki gibi strong referans oluşturmamak için delegate objemizi weak olarak tanımlamamız gerekmektedir. Burda dikkat edilmesi gereken protokolleri weak olarak tanımlayabilmek için class‘tan türetmemiz gerekmektedir.

Serinin bir sonraki yazısında Xcode Memory Graph özelliğinin nasıl kullanıldığından bahsedeceğim.

Kolay gelsin.

--

--