Memory Graph: nedir, nesne grafi ve döngüsel referansları tespit etme

Yazar: IT Sectr Yayınlanma: 2026-05-07 Okuma süresi: 10 dk

Memory Graph, Xcode Debug Navigator'ın görsel bir aracıdır ve uygulamanın belleğindeki nesneleri karşılıklı referanslarıyla birlikte bir grafik olarak görüntüler. Heap dump'ın aksine, Memory Graph yalnızca bir nesne listesi değil, her düğümün bir nesne ve her kenarın bir referans (strong, weak, unowned) olduğu yönlendirilmiş bir referans grafi gösterir. Apple WWDC 2018'e göre, bu araç, heap dump'ın ham verilerini analiz etmeye gerek kalmadan saniyeler içinde retain cycles ve bellek sızıntılarını görsel olarak tespit etmenizi sağlar.

Önemli noktalar

  • Memory Graph, Xcode belleğindeki nesnelerin görsel bir grafi olup, nesneler arasındaki referansları gerçek zamanlı olarak gösterir.
  • Retain cycle, grafikte kapalı bir döngü ile tespit edilir — iki veya daha fazla nesne birbirini strong referanslarla referans alır.
  • Backtrace, grafiğin her kenarı için referansın nerede ve ne zaman oluşturulduğunu göstererek sızıntı kaynağının aranmasını kolaylaştırır.
  • Filtreleme, sınıf adına ve referans türüne (strong/weak) göre sorunlu nesneleri hızlıca ayırmanızı sağlar.
  • Entegrasyon, Xcode'daki Memory Report ile bellek tüketimindeki değişiklikleri gerçek zamanlı olarak izlemenizi sağlar.

Memory Graph nedir ve nasıl çalışır

Memory Graph, Xcode Debug Navigator'ın bir bileşenidir (Xcode 10, WWDC 2018'de tanıtıldı) ve hata ayıklanan sürecin belleğindeki tüm nesnelerin yönlendirilmiş bir grafiğini oluşturur. Grafiğin her düğümü bir sınıf örneğidir (Objective-C veya Swift), her kenar başka bir nesneye yapılan referanstır. Kenarın rengi referans türünü belirtir: mavi — strong, yeşil — weak, gri — unowned. Grafik, LLDB ve Objective-C runtime verilerine dayanarak oluşturulur, bu nedenle doğru çalışma için uygulamanın semboller etkinleştirilmiş Debug yapılandırmasında derlenmesi gerekir.

Çalışma prensibi: uygulama bir breakpoint'te duraklatıldığında, Xcode LLDB aracılığıyla runtime'dan tüm canlı nesneleri ve referanslarını ister. LLDB, tam grafiği oluşturmak için objc_getClassList'i kullanır ve ayırma bölgeleri üzerinde yinelenir. ARM64'te (Apple Silicon), yavaşlama olmadan ayırma takibi için ek donanım araçları kullanılır. Grafik oluşturma süresi, yığın boyutuna bağlıdır: tipik bir iOS uygulaması (50–200 MB) için grafik 1–3 saniyede oluşur.

Apple'a göre Memory Graph, kod değişikliği veya enstrümantasyon eklemeden retain cycles'ları görselleştirebilen tek araçtır. Instruments Leaks'in aksine, Memory Graph Xcode içinde gerçek zamanlı olarak çalışır ve ayrı bir profil oluşturucu başlatılmasını gerektirmez. Bu, onu geliştirme sırasında hızlı bellek sızıntısı teşhisi için ilk tercih edilen araç haline getirir.

Memory Graph ile heap dump arasındaki fark

Heap dump, sayılarla (shallow size, retained size) birlikte tüm nesnelerin bir tablosunu sağlar — nicel analiz için idealdir. Memory Graph, bağlantıların görsel bir resmini sağlar — döngüsel referansları bulmak için idealdir. Araçlar birbirini tamamlar: önce hızlı retain cycle tespiti için Memory Graph, ardından hassas retained size ölçümü için Instruments Allocations aracılığıyla heap dump. objc.io'ya göre, her iki yöntemin kombinasyonu bellek sızıntısı senaryolarının %95'ini kapsar.

Memory Graph ile retain cycles tespiti

Retain cycle, iki veya daha fazla nesnenin birbirini strong referanslarla tutarak kapalı bir döngü oluşturduğu bir durumdur. ARC, her nesnenin retain count'u asla sıfıra ulaşmadığı için böyle bir döngüyü serbest bırakamaz. Klasik bir örnek: ViewController ve View; View'in self'i (ViewController) yakalayan bir closure'a strong referansı vardır. Memory Graph bu tür döngüleri halkalar (döngüler) olarak gösterir ve hızlı tanımlama için vurgular.

Xcode bir retain cycle tespit ettiğinde, onu turuncu bir çerçeveyle vurgular ve Debug Navigator'da bir uyarı gösterir. Döngüye tıkladığınızda, kapalı döngüyü oluşturan referans zincirini görürsünüz. Geliştiricinin yalnızca hangi strong kenarın weak olması gerektiğini belirlemesi gerekir — genellikle bu, alt nesneden üst nesneye yapılan bir referanstır (örneğin, delegate veya closure).

swift
class ViewController: UIViewController {
    let service = DataService()

    override func viewDidLoad() {
        super.viewDidLoad()
        // ❌ Retain cycle: ViewController → service → closure → ViewController
        service.fetchData { self.updateUI($0) }
    }

    func updateUI(_ data: Data) {}
}

class DataService {
    var completion: ((Data) -> Void)?

    func fetchData(handler: @escaping (Data) -> Void) {
        self.completion = handler
    }
}

Memory Graph'te bir üçgen göreceksiniz: ViewController → DataService → closure → ViewController. Çözüm, self yakalamasını zayıf yapmaktır: [weak self]. Düzeltmeden sonra Memory Graph, closure'dan ViewController'a yeşil bir kenar gösterecek ve retain cycle kaybolacaktır.

swift
// Düzeltilmiş kod — self'in zayıf yakalanması
service.fetchData { [weak self] data in
    guard let self else { return }
    self.updateUI(data)
}

Xcode'da Memory Graph Debugger arayüzü

Memory Graph Debugger arayüzü üç panelden oluşur: sol — örnek sayılarıyla birlikte tüm canlı nesnelerin listesi (sınıfa göre gruplanmış); orta — sürüklenebilir düğümlerle görsel bir grafik; sağ — seçili nesne veya kenar için bir denetçi. Nesne listesi şunları gösterir: sınıf simgesi, bellekteki örnek sayısı, toplam retained size ve tüm yığının yüzdesi. Sınıf adına göre filtreleme, düzenli ifadeleri destekler.

Grafikte gezinme

Grafik düğümleri, okunabilirliği artırmak için sürüklenebilir. Bir düğüme çift tıklamak, nesne hakkında ayrıntılı bilgi açar: türler ve değerlerle birlikte tüm özellikleri, her özellik için çağrı yığını (backtrace) ve retain/release geçmişi. Backtrace önemli bir özelliktir: nesneye olan referansı hangi kod satırının oluşturduğunu gösterir. Bu, tüm kodu manuel olarak incelemek zorunda kalmadan sızıntı kaynağını bulmanızı sağlar.

Karmaşık grafikler için Xcode, Layout → Hierarchical veya Cluster aracılığıyla otomatik düzen sağlar. Hiyerarşik düzen, kök nesneleri üste ve alt nesneleri alta yerleştirerek zincir aramasını basitleştirir. Küme gruplaması, ilgili nesneleri kümeler halinde gruplandırır ve grafik birden çok izole grup içerdiğinde kullanışlıdır. Apple'a göre, çoğu uygulama için hiyerarşik düzen önerilir — sezgiseldir ve görsel analiz için daha az zaman alır.

lldb
// Memory Graph'ın dahili olarak kullandığı LLDB komutları
(lldb) script import lldb.macosx.heap
(lldb) script heap.find_variable("viewController")
0x600000c4b80: ViewController
(lldb) script heap.refs 0x600000c4b80
0x600000c4b80 -> 0x600003a4c00 (DataService)
    ivar: _service, offset: 16

Grafik analizi: sızıntıları bulma ve düzeltme

Memory Graph analizine sistematik bir yaklaşım birkaç aşamayı içerir. Aşama 1: uygulamayı çalıştırın, potansiyel olarak sızıntıya neden olacak bir senaryo gerçekleştirin (ekranı açma/kapatma, ağ isteği yapma). Aşama 2: Debug Navigator'da Memory Graph düğmesine tıklayın — Xcode grafiği oluşturur. Aşama 3: sol panelde turuncu retain cycle uyarılarını kontrol edin. Aşama 4: şüpheli nesneler için Show only cycles seçeneğini kullanın — yalnızca döngüsel referanslara dahil olan düğümler görüntülenecektir.

Kaynağı bulmak için backtrace kullanımı

Bir retain cycle bulunduğunda, döngünün kenarına tıklayın ve denetçi panelini açın. Backtrace bölümü, bu referansın oluşturulduğu andaki çağrı yığınını gösterir. Örneğin, kenar bir closure'dan self'e gidiyorsa, backtrace closure'ın hangi yöntemde ve hangi kod satırında oluşturulduğunu gösterecektir. Bu, tahmin etme ihtiyacını ortadan kaldırır — sorunlu referansın oluşturulduğu noktayı hemen görürsünüz. WWDC Labs'e göre, backtrace analizi retain cycle teşhis süresini 15–20 dakikadan 2–3 dakikaya düşürür.

swift
class ProfileViewController: UIViewController {
    var profileView: ProfileView!

    override func viewDidLoad() {
        super.viewDidLoad()
        profileView = ProfileView()
        // Memory Graph retain cycle'ı burada gösterecek
        profileView.onTap = { [unowned self] in
            // ⚠️ unowned, self nil olduğunda crash'e neden olabilir
            self.navigateToDetail()
        }
    }

    func navigateToDetail() { }
}

// ✅ Doğru: [weak self] + guard let self
profileView.onTap = { [weak self] in
    guard let self else { return }
    self.navigateToDetail()
}

Gereksiz nesneleri filtreleme

Memory Graph binlerce nesne görüntüleyebilir ve aramayı zorlaştırabilir. Sol paneldeki filtreleri kullanın: yalnızca bu sınıfın örneklerini görüntülemek için bir sınıf adı girin (örneğin, ProfileViewController). Ardından, serbest bırakılmış olması gereken bir örneği seçin (ekran kapalıysa ancak nesne duruyorsa). Show Reachable From'u uygulayın — yalnızca bu nesneyle ilgili referanslar görüntülenecek, grafiğin geri kalanı gizlenecektir.

Memory Graph kullanımı için pratik ipuçları

Deneyimli geliştiriciler, Memory Graph'ı yalnızca sızıntıları bulmak için değil, aynı zamanda proaktif bellek kontrolü için de kullanır. Her büyük mimari değişiklikten sonra Memory Graph'ı kontrol edin — yeni bir delegate, closure veya NotificationCenter aboneliği eklemek. Sadece tipik bir senaryo çalıştırın ve nesnelerin doğru şekilde serbest bırakıldığından ve retain cycles olmadığından emin olun. Bu 2–3 dakika sürer ancak saatler süren sonraki hata ayıklamayı önler.

Memory Report ile kombinasyon

Xcode'daki Memory Report (Debug Navigator sekmesi), gerçek zamanlı bellek tüketimi grafiği gösterir. Memory Graph ile birlikte kullanın: tüketim aniden arttığında Memory Graph'ı açın. Örneğin, resim yükleyen hücrelerle dolu uzun bir listede gezinirken, Memory Graph hangi nesnelerin oluşturulduğunu ve hangilerinin serbest bırakıldığını gösterir. Nesne sayısı azalmadan artıyorsa — bu, çökmeye neden olmadan önce görülebilen potansiyel bir sızıntıdır. Apple'a göre, Memory Graph + Memory Report kombinasyonu, Xcode 12'den itibaren tüm iOS geliştiricileri için önerilen iş akışıdır.

objective-c
// Objective-C'de delegation yoluyla sızıntı örneği
@interface DownloadManager : NSObject
@property (strong) id delegate; // ❌ Weak olmalı!
@end

@implementation DownloadManager
// Memory Graph retain cycle'ı gösterecek:
// ViewController → DownloadManager.delegate → ViewController
@end

// Düzeltme: weak property
@property (weak) id delegate;

Closure'ların profillenmesi

Closure'lara özellikle dikkat edin — Swift'te retain cycles'ların en yaygın kaynağı. Bir nesnenin özelliği olarak saklanan bir closure içinde self yakalandığında klasik bir döngü oluşur. Memory Graph bunu, yakalanan nesnelere mavi kenarlarla bağlı bir closure ({} sembolü olan bir düğüm) olarak görüntüler. Özellikle asenkron çağrılarda, GCD, Combine ve SwiftUI'de kullanılan tüm closure'ları düzenli olarak kontrol edin. Point-Free istatistiklerine göre, Swift projelerindeki sızıntıların %90'ı self'i yakalayan closure'larla ilgilidir.

Sıkça sorulan sorular

Memory Graph yalnızca Objective-C için mi çalışır yoksa Swift için de mi?

Memory Graph, Objective-C runtime'ı kullandığı için her iki dil için de çalışır. ObjC ile uyumlu Swift nesneleri (@objc ile işaretlenmiş NSObject alt sınıfları) tam olarak görüntülenir. ObjC köprüsü olmayan saf Swift yapıları ve sınıfları sınırlı olarak görünür.

Memory Graph neden bazı nesneleri göstermiyor?

Nesnelerin Objective-C runtime'a kayıtlı olması gerekir. Swift değer türleri (struct, enum) görüntülenmez. Sınıfın NSObject'ten miras aldığından veya Memory Graph'te görünürlük için @objc özniteliğini kullandığından emin olun.

Grafikteki kenar renkleri nasıl yorumlanır?

Mavi — strong referans, nesneyi tutar. Yeşil — weak referans, yaşam döngüsünü etkilemez. Gri — unowned referans. Retain cycle yalnızca mavi kenarlardan oluşur.

Memory Graph uygulamayı yavaşlatır mı?

Grafik oluşturma, uygulamayı 1–3 saniye duraklatır ve Xcode bellek tüketimini geçici olarak 200–500 MB artırabilir. Uygulamanın kendisi yavaşlamaz çünkü inceleme breakpoint duraklaması sırasında gerçekleşir.

Memory Graph analiz için dışa aktarılabilir mi?

Xcode, grafiğin doğrudan dışa aktarılmasını desteklemez. Belgeler için ekran görüntüsü veya programatik veri çıkarma için lldb betiği heap.find_variable kullanın. Ayrıntılı analiz için, heap dump ile birlikte Instruments Allocations kullanın.

Özet

  • Memory Graph, Xcode'da bellek içindeki nesneleri referanslarıyla birlikte grafik olarak gösteren görsel bir araçtır.
  • Retain cycle, mavi (strong) kenarlardan oluşan kapalı bir döngü olarak gösterilir — Xcode onu turuncuyla vurgular.
  • Backtrace, grafiğin her kenarı için sorunlu referansın oluşturulduğu kod içindeki tam konumu gösterir.
  • Filtreleme, sınıflara ve referans türlerine göre binlerce nesne içeren bir grafikteki sızıntıları ayırmanızı sağlar.
  • Closure'lar, Swift'te retain cycles'ların ana kaynağıdır, Memory Graph bunları {} düğümleri olarak gösterir.
  • Weak ve unowned, döngüyü kırmak için çözümlerdir, ancak nil'de güvenlik nedeniyle weak tercih edilir.
  • Mimari değişikliklerden sonra düzenli Memory Graph kontrolleri, projede bellek gerilemesini önler.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun