Nasıl olabilir? Yerel bir değişkenin belleğine işlevi dışında erişilemez mi?
Bir otel odası kiralıyorsunuz. Komodinin üst çekmecesine bir kitap koyup uyuyorsun. Ertesi sabah kontrol, ama anahtarınızı geri vermek "unutmak". Anahtarı çalıyorsun!
Bir hafta sonra, otele geri dönersiniz, check-in yapmaz, çalıntı anahtarınızla eski odanıza girer ve çekmeceye bakarsınız. Kitabınız hala orada. Şaşırtıcı!
Nasıl olabilir? Eğer oda kiralamadıysanız bir otel odası çekmecesinin içeriğine erişilemiyor mu?
Tabii ki, bu senaryo gerçek dünyada sorun olabilir. Artık odada bulunma yetkiniz olmadığında kitabınızın kaybolmasına neden olan gizemli bir güç yoktur. Çalınan bir anahtarla bir odaya girmenizi engelleyen gizemli bir güç de yoktur.
Otel yönetimi kitabınızı kaldırmak için gerekli değildir . Onlarla bir anlaşma yapmadınız, eğer bir şeyleri geride bırakırsanız, sizin için parçalayacaklarını söylediler. Yasadışı bir şekilde odanıza geri dönmek için çalınan bir anahtarla tekrar girerseniz, otel güvenlik personelinin sizi gizlice yakalaması gerekmez . Onlarla bir sözleşme yapmadınız. sonradan beni durdurman gerekiyor. " Bunun yerine, bir sözleşme "Daha sonra odama gizlice geri dair söz" dedi onlarla bir sözleşme imzaladı sen kırdı .
Bu durumda her şey olabilir . Kitap orada olabilir - şanslısın. Başkasının kitabı orada olabilir ve sizinki otelin fırında olabilir. İçeri girdiğinizde birisi orada olabilir, kitabınızı parçalara ayırabilir. Otel tablo ve kitap tamamen kaldırılmış ve bir gardırop ile değiştirmiş olabilir. Tüm otel hemen parçalanmış ve yerine bir futbol stadyumu olabilir ve sinsice dolaşırken bir patlamada ölecek.
Ne olacağını bilmiyorsun; otelin kullanıma ve yasadışı sonra kullanmak için bir anahtar çaldığında, sen çünkü öngörülebilir, güvenli dünyada yaşama hakkı vazgeçti Eğer sistemin kurallarını kırmak için seçti.
C ++ güvenli bir dil değildir . Neşeyle sistemin kurallarını çiğnemenize izin verecektir. Yasadışı ve aptalca bir şey yapmaya çalıştığınız bir odaya geri dönme ve artık orada bulunmayan bir masadan dolaşmak gibi, C ++ sizi durdurmayacak. C ++ 'dan daha güvenli diller, örneğin, tuşlar üzerinde çok daha sıkı denetime sahip olarak, gücünüzü kısıtlayarak bu sorunu çözer.
GÜNCELLEME
Kutsal iyilik, bu cevap çok dikkat çekiyor. (Neden olduğundan emin değilim - bunu sadece "eğlenceli" küçük bir benzetme olarak gördüm, ama her neyse.)
Bunu biraz daha teknik düşüncelerle güncellemenin almanca olabileceğini düşündüm.
Derleyiciler, bu program tarafından manipüle edilen verilerin depolanmasını yöneten kod üretme işindedir. Belleği yönetmek için kod üretmenin birçok farklı yolu vardır, ancak zamanla iki temel teknik yerleşmiştir.
Birincisi, depolamadaki her baytın "kullanım ömrünün" - yani, bazı program değişkenleriyle geçerli olarak ilişkilendirildiği zaman periyodunun - önceden kolayca tahmin edilemediği bir çeşit "uzun ömürlü" depolama alanına sahip olmaktır. zaman. Derleyici, gerektiğinde depolamayı dinamik olarak nasıl ayıracağını ve artık gerekmediğinde geri almayı bilen bir "yığın yöneticisine" çağrı oluşturur.
İkinci yöntem, her bir baytın ömrünün iyi bilindiği "kısa ömürlü" bir depolama alanına sahip olmaktır. Burada, yaşamlar “iç içe geçme” modelini izler. Bu kısa ömürlü değişkenlerin en uzun ömürlüleri, diğer kısa ömürlü değişkenlerden önce tahsis edilecek ve en son serbest bırakılacaktır. Daha kısa ömürlü değişkenler, en uzun ömürlü değişkenlerden sonra tahsis edilecek ve önlerinde serbest bırakılacaktır. Bu daha kısa ömürlü değişkenlerin ömrü, daha uzun ömürlü değişkenlerin ömrü içinde “iç içe geçmiştir”.
Yerel değişkenler ikinci paterni takip eder; bir yöntem girildiğinde, yerel değişkenleri canlanır. Bu yöntem başka bir yöntem çağırdığında, yeni yöntemin yerel değişkenleri canlanır. İlk yöntemin yerel değişkenleri ölmeden ölürler. Lokal değişkenlerle ilişkili depoların yaşam sürelerinin başlangıcı ve bitişlerinin göreceli sırası önceden çalışılabilir.
Bu nedenle, yerel değişkenler genellikle bir "yığın" veri yapısında depolama olarak üretilir, çünkü bir yığın üzerine itilen ilk şeyin attığı son şey olacağı özelliğine sahiptir.
Otel sadece oda sırayla kiraya karar verir gibi ve oda sayısı daha yüksek olan herkese kadar kontrol edemez gibi.
Öyleyse yığını düşünelim. Birçok işletim sisteminde, iş parçacığı başına bir yığın alırsınız ve yığın belirli bir sabit boyuta ayrılır. Bir yöntemi çağırdığınızda, şeyler yığının üzerine itilir. Daha sonra orijinal poster burada olduğu gibi yığına bir işaretçi iletirseniz, bu tamamen geçerli bir milyon bayt bellek bloğunun ortasına bir işaretçi olur. Bizim benzetimizde, otelden çıkış yaparsınız; bunu yaptığınızda, sadece en yüksek numaralı odadan kontrol ettiniz. Kimse sizden sonra check-in yapar ve odanıza yasadışı olarak geri dönerseniz, tüm eşyalarınızın hala bu özel otelde olması garanti edilir .
Geçici mağazalar için yığınlar kullanıyoruz çünkü gerçekten ucuz ve kolay. Yerlilerin depolanması için bir yığın kullanmak için bir C ++ uygulaması gerekli değildir; öbeği kullanabilir. Olmaz, çünkü bu programı yavaşlatır.
Yığında bıraktığınız çöplere dokunulmadan bırakılması için bir C ++ uygulaması gerekli değildir, böylece daha sonra yasadışı olarak geri gelebilirsiniz; derleyicinin yeni boşalttığınız "odada" her şeyi sıfıra çeviren kod üretmesi son derece yasaldır. Bunu yapmaz çünkü tekrar, bu pahalı olurdu.
Yığın mantıksal olarak küçüldüğünde, eskiden geçerli olan adreslerin hala belleğe eşlendiğinden emin olmak için bir C ++ uygulaması gerekli değildir. Uygulamanın işletim sistemine "bu yığının bu sayfasını şimdi yaptık. Aksi söyleyene kadar, daha önce geçerli yığın sayfasına dokunursa işlemi yok eden bir istisna yayınla" deme izni var. Yine, uygulamalar aslında bunu yapmaz, çünkü yavaş ve gereksizdir.
Bunun yerine, uygulamalar hata yapmanıza ve ondan kurtulmanıza izin verir. Çoğu zaman. Bir güne kadar gerçekten korkunç bir şey ters gider ve süreç patlar.
Bu sorunlu. Çok fazla kural var ve onları yanlışlıkla kırmak çok kolay. Kesinlikle birçok kez var. Ve daha da kötüsü, sorun genellikle, bellek, bozulma gerçekleştikten sonra milyarlarca nanosaniye olarak tespit edildiğinde, kimin berbat ettiğini anlamanın çok zor olduğu durumlarda ortaya çıkar.
Daha fazla bellek güvenli dil bu sorunu gücünüzü kısıtlayarak çözer. "Normal" C # 'da bir yerelin adresini alıp iade etmenin ya da daha sonra saklamak için bir yol yoktur. Bir yerelin adresini alabilirsiniz, ancak dil akıllıca tasarlanmıştır, böylece yerel sonların ömründen sonra kullanmak imkansızdır. Yerel adresini alıp geri geçmek için, bir ziyaretini özel "güvenli olmayan" modunu derleyici koymak zorunda ve muhtemelen yaptığını gerçeğine çağrı dikkatine, programınızda "güvenli olmayan" kelimesini koymak kurallara aykırı olabilecek tehlikeli bir şey.
Daha fazla okuma için:
address of local variable ‘a’ returned
; valgrind gösterileriInvalid write of size 4 [...] Address 0xbefd7114 is just below the stack ptr