Merhaba ve hoş geldiniz.
Bu derste, çağrı yığınından, tam olarak ne olduğundan ve programınızda hata ayıklamaya yardımcı olmak için
onu nasıl okuyabileceğinizden biraz bahsetmek istiyorum.
Esasen çağrı yığınının ne olduğunu gösteren bir yığın izi, uygulamanız ölümcül bir hata nedeniyle
çöktüğünde oluşturulur.
Yığın teriminin kullanılmasının nedeni, programlamada yaygın olan bir veri yapısına atıfta bulunmasıdır.
Yığın, LIFO (son giren ilk çıkar) olarak bilinen bir veri yapısıdır ve veriler bu şekilde saklanır.
Eklenen son veri öğesi, geri aldığınız ilk veri öğesidir.
Bunu bir krep yığını yiyormuşsunuz gibi düşünebilirsiniz, ilk krepi en alta
eklersiniz.
Son krep en üstte.
Onları yemeye gittiğinizde, eklenen sonuncuyu yersiniz.
Bu nedenle, programınız çöktüğünde yığın izi çok yararlıdır çünkü hata ayıklamanıza yardımcı olacak bilgiler
içerir.
Yani yığın izi, hataya yol açan işlev çağrılarının bir listesini gösterir.
Ve bir programda ana fonksiyonunuzu çağırdığınızda ne olur, bu giriş noktasıdır.
Ana fonksiyon diğer fonksiyonları çağıracaktır.
Bu işlevler diğer işlevleri çağıracak ve uygulanan ya da çağrılan tüm bu işlevler yığına
yerleştirilecektir.
Ve böylece bir program çöktüğünde, çağrı yığını size çağrılan son işlevi ve hataya
neden olan belirli kod satırını söyleyecektir.
Yani Callstack pek çok iyi bilgi içeriyor.
İstisnanın veya ölümcül hatanın oluşmasına neden olan kodun dosya adını ve satır numaralarını
içerecektir.
Yığının en üstünde hataya neden olan son çağrı bulunur ve iç içe çağrılar olabilir.
Yığının en altında, hatayı çağırmak için çağrı zincirini başlatan ilk çağrı yer alır.
Genellikle C'de main rutininde olursanız, main'i çağırırsınız, main başka bir fonksiyonu çağırır, o da başka bir
fonksiyonu çağırır ve bu böyle devam eder.
Ve sonra o son satır ayrıntılı.
Uygulama için uygulama çöktüğünde çok ama çok yardımcı oluyor.
Dolayısıyla bir C programı çöktüğünde, bir segmentasyon hatası oluşturabilir ve bu size çok fazla bilgi
vermez.
Bu sadece kötü bir şey olduğu anlamına gelir.
Bu aynı zamanda bir çekirdek dosya oluşturacaktır.
Çağrı yığınını içeren çekirdek dosyasını analiz edebilirsiniz, bu da çökmeniz için soruna neden
olan tam kod satırını size söyleyecektir.
Bu yüzden uygulamanızda çökmeye neden olan çağrıyı bulmanız gerekir.
Ve çağrı yığını muhtemelen bunu yapmanın en iyi yoludur.
Ve her zaman o çekirdek dosyaya bakmanız gerekmez.
Ayrıca bir hata ayıklayıcı ile GDB kullanarak çağrı yığınını analiz edebilirsiniz.
Ve size bunun neye benzediğini göstermek istiyorum.
Bir programcı ayrıca yığın izini istediği zaman dökebilir.
Böylece bir hata yakalarsanız veya ölümcül bir hata olabileceğini fark ederseniz, neler olup bittiğini görmek
için çağrı yığınını dökebilirsiniz.
Hatanın ne zaman gerçekleşeceğini gerçekten bilmiyorsanız, belirli bir
çağrıya yol açan mevcut izleri görmek için çağrı yığınını dökebilirsiniz.
GDB kullanırken, çağrı yığını aşağıdaki gibi görünecektir.
GDB'de hata ayıklayıcıyı çalıştırırken menü aracılığıyla çağrı yığınına erişebilirsiniz ve
size bunu nasıl yapacağınızı göstereceğim, ancak bu neye benziyor ve burada göreceğiniz şey bir sayı,
bir adres ve ardından işlevdir.
Buradaki belirli çağrı yığınında çok sayıda farklı çağrı vardır, bu nedenle çok sayıda farklı iç içe geçme ve çok sayıda farklı
işlev çağrısı yapıyor olmalıdır.
Ancak 22. satırdaki yığının en altında GTK main yazıyor.
Bu da demek oluyor ki.
Bu, muhtemelen ana işlevi yürüttüğü anlamına gelir.
Ve sonra 21. satırda, yürütülmüş gibi görünüyor.
Belki bir ifade ana döngü çalıştır diyordur.
Ve sonra G main context iterate adlı bir işlev çağrılmış gibi görünüyor.
Ve bu işlevin içinde, bir IAG ana bağlam gönderme işlevine başka bir çağrı olduğunda
bazı şeyler vardı.
Yani bir iterate fonksiyonu, ardından bir dispatch fonksiyonu vardı ve 18. satırdaki soru işaretleri hata
ayıklama bilgisi olmadığı anlamına geliyor.
Orada ne olduğunu bilmiyor.
İşte bu yüzden programınızı oluştururken ya yayınlanmak üzere oluşturursunuz ya da hata ayıklama
bilgileriyle oluşturursunuz.
Hata ayıklama bilgileriyle derlediğinizde, derlediğinizde ekstra bilgiler içerir, böylece çalıştırdığınızda
çağrı yığınlarına bakabilirsiniz.
Serbest bıraktığınızda, serbest bırakmak için bir şeyler inşa edin.
Yürütülebilir dosya çok daha küçüktür ve bu bilgileri içermeyebilir.
Daha fazla soru işareti içerebilir.
Ancak bu aynı zamanda herhangi bir kütüphaneyi, herhangi bir ek programı çağırıp çağırmadığınızı da söyleyecek, bunları çağıracak ve oradan
size çağrı yığınını söyleyecektir.
Ancak bunun gösterdiği şey, yine, en üstteki çağrı için farklı iç içe geçmiş olaylardır, önemli olan
budur, çünkü bu, çökmeye neyin neden olduğunu gösterecektir.
Görünüşe göre bu özel çağrı yığınında, iç yenileme bir soruna neden oluyordu.
Ve 22. satırdan sıfırıncı satıra kadar farklı kodların birçok farklı çağrımı olduğunu görebilirsiniz.
Ancak nihai program sıfırıncı satırdaki çağrı yığınlarında çöküyor.
Ayrıca program çalışırken çağrı yığınlarına bakarak bilgileri görebilir ve böylece geriye doğru iz sürebilirsiniz.
Yani bir fonksiyonun içine bir kesme noktası koyarsanız, hata ayıklama yaparsınız, hata ayıklayıcıyı bunun üzerinde çalıştırırsınız.
Hata ayıklayıcı bu kesme noktasında duracaktır.
Daha sonra çağrı yığınını getirebilirsiniz ve size o kod satırına nasıl ulaştığınızı söyleyecektir.
Bu işlev, bu işlevden önce çağrılmıştır.
Ve yine, genellikle ana işlevle başlayacaktır.
Yığın ve kavramına ve bellekte nasıl yer aldığına aşina iseniz farklı çerçevelere de geçebilirsiniz,
farklı çerçevelere bakabilirsiniz, ancak bu, C'deki temel çökmeleri bulmak için çok kullanışlı bir
araçtır ve okunması çok kolaydır.
Sadece en üste bakarsanız ve çağrı yığını hakkında pek bir şey bilmiyorsanız,
en üste bakıp, Oh, bu bir kaynak, bu çökmeye neden olan bir kod satırı diyebilirsiniz.
İşte internette bulduğum güzel bir örnek.
Excma.
Edu.
Bu, işlev çağrı yığını örneklerini göstermektedir.
Koddaki bir örneğe bakarsak, göreceğimiz gibi sadece basit bir kodumuz var.
Hesaplamalar gerçekten önemli değil.
Temelde sadece bazı fonksiyonları çağırıyoruz.
Yani bu mogrify fonksiyonuna ve bu truly half fonksiyonuna sahibiz ve main bir mogrify fonksiyonunu çağıracak
ve sonra truly half'i çağıracak ve sonra mogrify'ı çağıracak, böylece çağrı yığınını
ve bu çağrılarda nasıl göründüğünü temel olarak main'de basit bir kesme noktası ayarlayarak ve sonra ilerledikçe
ve çağrılar yaptıkça çağrı yığınına bakarak gösterebiliriz.
Yani yine, kesme noktalarına ve bunun gibi bilgilere daha aşina olacağız.
Ancak çağrı yığınını çok hızlı bir şekilde göstermek istiyorum ve aslında daha sonra çağrı yığınının daha ayrıntılı
bir örneğini vereceğiz.
Burada bir kesme noktası belirledim.
Devam edip bunu derleyebilirim ve hata ayıklayıcıyı başlatabilirim ve kesme noktasına ulaşırız.
Ve şimdi fark edeceğiniz şey, tüm hata ayıklayıcı menüsünü burada sağ tarafta altta görebilirsiniz ve
çağrı yığınını göreceksiniz.
Bunu biraz daha büyütelim.
Ancak tam 14. satırda durduğunda, burada sadece bazı atama ifadeleri vardır ve çağrı yığınının main'i
gösterdiğini göreceksiniz.
Bunun üzerinden geçip bir sonraki satıra gidersek, aslında Mogrify'ı çağırmadan önce 15. satıra
gittiğini görebiliriz, değil mi?
Ve böylece çağrı yığınının Main ile kaldığını görürsünüz.
İçeri girersek, şimdi çağrı yığınının Mogrify'ı gösterdiğini göreceksiniz.
Yani aslında bu fonksiyonun içindeyiz.
Bunu aşabiliriz.
Böylece ilk satırı çalıştırır ve ardından temp değerini döndürür.
Hala o fonksiyonda kalıyor ve sonra 16. satırda F yazdırma işlemini yaptığı yere geri dönüyor, çağrı yığınının nasıl değiştiğini
görüyorsunuz.
Daha sonra 18. satıra gidiyoruz, main'de stack stills'i çağırıyoruz ve gerçekten yarım fonksiyona adım atıyoruz.
Ve şimdi çağrı yığınının değiştiğini görüyorsunuz, burada gerçekten en üstteki işlevin yarısı
her zaman en son çağrılan işlevdir.
Tekrar adım atıyoruz ve hala gerçekten yarıda olduğumuzu görüyorsunuz.
Main'e geri dönüyoruz, 19. satırda bir şey yazdırıyoruz, 21. satıra gidiyoruz.
Yine çağrı yığınında gördüğünüz modify fonksiyonuna atlıyoruz, atlıyoruz, atlıyoruz ve sonunda 23. satırdaki
nihai sonucu yazdırıyoruz ve programdan geri dönüyoruz.
Ancak çağrı yığını yine bize bir fonksiyondan diğerine çağrılan fonksiyonların sırasını gösterir.
Dolayısıyla, iç içe geçmiş fonksiyonlarınız varsa, bu daha da karmaşık hale gelebilir.
Çağrı yığınının avantajı, örneğin dördüncü satırda çöken bir kod satırınız varsa, en üstte satırın
çöktüğü yeri içeren bir çağrı yığınına sahip olmanızdır.
Böylece çağrı yığınını inceleyerek en son hangi kod satırının çağrıldığını görebilirsiniz
ve bu da size hangi kod satırının çöktüğünü söyleyecektir.
Ancak programınız çöktüğünde bu aracı kullanmak isteyeceksiniz.
Teşekkür ederim.