Fiziksel Sızıntı
GC'nin ele aldığı hatalar (en azından bir dış gözlemciye), bir programcının dilini, kitaplıklarını, kavramlarını, deyimlerini vb. İyi tanıyan şeyler yapmaz. Ancak yanılıyor olabilirim: manuel hafıza kullanımı kendinden karmaşık mı?
Bellek yönetimini el ile mümkün kılan ve mümkün olduğunca telaffuz edilen C ucundan geliyoruz, böylece aşırı uçları karşılaştırıyoruz (C ++ çoğunlukla GC olmadan bellek yönetimini otomatikleştiriyor), GC'yi karşılaştırırken "gerçekten değil" derim. sızıntılara geliyor . Yeni başlayanlar ve bazen bir profesyonel bile free
verilenler için yazmayı unutabilir malloc
. Kesinlikle oldu.
Ancak, valgrind
kaçak tespiti gibi , kodun uygulanmasında, bu tür hataların tam kod satırına kadar / nerede meydana geldiği zaman hemen farkedilecek araçlar vardır . Bu CI'ye entegre edildiğinde, bu tür hataları birleştirmek neredeyse imkansız hale gelir ve bunları düzeltmek için kolay bir pasta olur. Bu yüzden hiçbir zaman makul bir standartta herhangi bir ekip / süreçte önemli bir şey değil.
Kabul edilirse, free
çağrılmadığı yerlerde test radarı altında uçan , belki de bozuk bir dosya gibi gizli bir harici giriş hatasıyla karşılaşıldığında, belki de sistem 32 bayt veya bir şey sızıntısı olduğu bazı egzotik uygulama durumları olabilir . Bunun kesinlikle iyi test standartları ve sızıntı tespit araçları altında bile gerçekleşebileceğini düşünüyorum, ancak neredeyse hiç gerçekleşmeyen bir şeyin üzerine biraz bellek sızdırmak da çok da önemli olmayacak. GC'nin önleyemeyeceği şekilde, genel uygulama yollarında bile büyük kaynakları sızdırabileceğimiz daha büyük bir sorun göreceğiz.
Ayrıca, bir nesnenin kullanım ömrünün bir tür ertelenmiş / asenkron işlem, belki başka bir iş parçacığı için uzatılması gerektiğinde, GC'nin takma biçimine benzeyen bir şey olmadan da zordur.
Sarkan Pointer
Daha fazla manuel bellek yönetimi türüyle asıl sorun bana sızıntı değil. C veya C ++ dilinde yazılan kaç tane yerel uygulama olduğunu biliyoruz. Linux çekirdeği sızdırıyor mu? MySQL? CryEngine 3? Dijital ses iş istasyonları ve birleştiriciler? Java VM sızdırıyor mu (yerel kodda uygulanıyor)? Photoshop?
Herhangi bir şey varsa, etrafa baktığımızda en sızan uygulamalar GC şemaları kullanılarak yazılmış olma eğilimindedir. Ancak, çöp toplama işleminde bir çarpma olarak ele alınmadan önce, yerel kodun bellek sızıntılarıyla hiç ilgisi olmayan önemli bir sorunu var.
Benim için mesele her zaman güvenlik oldu. Hatta zaman free
hafıza bir işaretçi üzerinden, kaynağa başka işaretçiler varsa, bunlar (geçersiz kılınan) işaretçileri sarkan hale gelecektir.
Bu sarkan işaretçilerin pointe'lerine erişmeye çalıştığımızda, neredeyse her zaman zor ve acil bir çökmeye neden olan bir segfault / erişim ihlali olmasına rağmen tanımsız davranışlarla karşılaşıyoruz.
Yukarıda listelediğim tüm bu yerel uygulamalar, potansiyel olarak, bu sorun nedeniyle öncelikle bir çökmeye yol açabilecek son derece gizli bir davaya sahiptir ve kesinlikle yerel kodda yazılmış çok sık sık ağır olan ve oldukça sık sık kullanılan kaliteli uygulamaların adil bir payı vardır. bu sorun nedeniyle büyük oranda.
... ve GC kullanıp kullanmadığınızdan bağımsız olarak kaynak yönetimi zordur. Pratik fark, kaynak yanlış yönetimine yol açan bir hata karşısında genellikle sızıntı (GC) veya çökme (GC olmadan) şeklindedir.
Kaynak Yönetimi: Çöp Toplama
Karmaşık kaynak yönetimi ne olursa olsun zor, manuel bir işlemdir. GC burada hiçbir şeyi otomatik hale getiremez.
Bu nesneye sahip olduğumuz örneğe bakalım, "Joe". Joe'ya üye olduğu birkaç kuruluş tarafından başvuruda bulunulur. Her ay ya da öylesine onlar kredi kartından bir üyelik ücreti almak.
Ayrıca ömrünü kontrol etmek için Joe'ya bir referansımız var. Diyelim ki, programcılar olarak artık Joe'ya ihtiyacımız yok. Bizi sinirlendirmeye başladı ve artık onunla uğraşarak zamanlarını boşa harcadığı bu örgütlere ihtiyacımız yok. Bu yüzden yaşam çizgisi referansını kaldırarak onu yeryüzünden silmeye çalışıyoruz.
... ama bekle, çöp toplama kullanıyoruz. Joe'ya yapılan her güçlü referans onu etrafta tutacak. Bu yüzden kendisine ait olduğu kuruluşlardan referansları kaldırıyoruz (aboneliği iptal ediyor).
... boğmacalar dışında, dergi aboneliğini iptal etmeyi unuttuk! Artık Joe hafızada kalıyor, bizi rahatsız ediyor ve kaynakları kullanıyor ve dergi şirketi de her ay Joe üyeliğini işlemeye devam ediyor.
Bu, çöp toplama şemaları kullanılarak yazılmış birçok karmaşık programın, sızıntı yapıp daha fazla bellek kullandıkça daha fazla bellek kullanmaya ve muhtemelen daha fazla işlemeye (tekrar eden dergi aboneliği) neden olmasına neden olabilecek ana hatadır. Bu referanslardan bir veya daha fazlasını kaldırmayı unuttular, böylece çöp toplayıcının sihirini tüm program kapanana kadar yapmasını imkansız hale getirdiler.
Ancak program çökmedi. Tamamen güvenli. Sadece hafızayı karıştırmaya devam edecek ve Joe hala oyalanacak. Pek çok uygulama için, konuya giderek daha fazla bellek / işlem yaptığımız bu tür sızdıran davranışlar, özellikle günümüzde makinelerimizde ne kadar bellek ve işlem gücü olduğu göz önüne alındığında, zorlu bir çöküşte çok tercih edilebilir.
Kaynak Yönetimi: Manuel
Şimdi Joe'ya işaretçiler ve manuel bellek yönetimini kullandığımız alternatifleri düşünelim:
Bu mavi bağlantılar Joe'nun ömrünü yönetmiyor. Onu yeryüzünün suratından çıkarmak istiyorsak, onu elle imha etmek istiyoruz, şöyle:
Şimdi bu normalde bizi her yere sarkan işaretçilerle bırakacaktı, o yüzden işaretçileri Joe'ya kaldıralım.
... yine aynı hatayı tekrar yaptık ve Joe'nun dergi aboneliğini iptal etmeyi unuttuk!
Şimdi hariç, sarkan bir işaretçi var. Dergi aboneliği Joe’nun aylık ücretini işleme koymaya çalıştığında, tüm dünya patlayacak - genellikle hemen sert bir çarpışma yaşanır.
Geliştiricinin bir kaynağa tüm işaretçileri / referansları el ile kaldırmayı unuttuğu aynı temel kaynak yanlış yönetimi hatası, yerel uygulamalarda birçok çökmeye neden olabilir. Normalde daha uzun süre çalıştıkları için hafızayı korumazlar, çünkü bu durumda genellikle düpedüz çarpışma olur.
Gerçek dünya
Şimdi yukarıdaki örnek gülünç basit bir diyagram kullanıyor. Bir gerçek dünya uygulaması, tam bir grafiği kapsayacak şekilde bir araya getirilmiş binlerce görüntü, bir sahne grafiğinde saklanan yüzlerce farklı türde kaynak, bazılarıyla ilişkili GPU kaynakları, diğerlerine bağlı hızlandırıcılar, yüzlerce eklentiye dağılmış gözlemciler gerektirebilir sahnede değişiklikler, gözlemciler gözlemleyen gözlemciler, animasyonlar ile senkronize edilmiş sesler, vb. gibi çeşitli varlık türlerini izlemek. Yukarıda tarif ettiğim yanlışlıktan kaçınmak kolay gibi görünebilir, ancak gerçek dünyada bu kadar basit değil Milyonlarca kod satırı kapsayan karmaşık bir uygulama için üretim kod temeli.
Bir kişinin, bir gün, bu kod tabanındaki kaynakları yanlış yönetme olasılığı oldukça yüksektir ve bu olasılık GC ile veya GC olmadan aynıdır. Asıl fark, bu hatanın sonucu olarak ne olacağını ve bu hatanın ne kadar çabuk tespit edildiğini ve düzeltileceğini de potansiyel olarak etkiler.
Kaçak vs Çarpışma
Şimdi hangisi daha kötü? Anında bir kaza ya da Joe'nun gizemli bir şekilde etrafta dolaştığı sessiz bir bellek sızıntısı?
Çoğu ikinciye cevap verebilir, ancak diyelim ki bu yazılım, muhtemelen günlerce saatlerce çalışacak şekilde tasarlandı ve bu eklenmiş Joe ve Jane’lerin her biri, gigabayt tarafından yazılımın bellek kullanımını artırıyor. Bu, kritik bir yazılım değil (çökmeler aslında kullanıcıları öldürmez), ancak performans açısından kritik bir yazılımdır.
Bu durumda, yaptığınız hatayı işaret ederek hata ayıklama sırasında hemen ortaya çıkan sert bir çarpışma, test prosedürünüzün radarı altında dahi uçabilecek sızdıran bir yazılım için tercih edilebilir.
Kapak tarafında, performansın amaç olmadığı, mümkün olan herhangi bir yöntemle çarpmamaları durumunda, kritik bir yazılımsa, sızıntı gerçekten tercih edilebilir.
Zayıf Referanslar
Zayıf referanslar olarak bilinen GC şemalarında bulunan bu fikirlerin bir melezi vardır. Zayıf referanslarla, bütün bu organizasyonlara, zayıf referans Joe’ya sahip olabiliriz, ancak güçlü referans (Joe’nun sahibi / yaşam çizgisi) ortadan kalktığında çıkarılmasını engelleyemeyiz. Bununla birlikte, Joe'nun artık bu zayıf referanslar arasında ne zaman artık bulunmadığını saptayabilmenin avantajlarından yararlanıyoruz, bu da kolayca tekrarlanabilen bir hata türünü almamızı sağlıyor.
Ne yazık ki, zayıf referanslar, neredeyse muhtemelen kullanılması gerektiği kadar kullanılmaz, bu nedenle çoğu zaman, bir kompleks C uygulamasından çok daha az cilalı olsalar bile, çoğu karmaşık GC uygulaması sızıntılara karşı duyarlı olabilir.
Her durumda, GC'nin hayatınızı kolaylaştırması veya zorlaştırması, yazılımınızın sızıntıları önlemesinin ne kadar önemli olduğuna ve bu tür karmaşık kaynak yönetimi ile ilgilenip ilgilenmediğine bağlıdır.
Benim durumumda, ben kaynaklar kullanıcıların gerçekten olabilir yukarıdaki çünkü böyle bir hatayı boşaltma isteği zaman o belleği serbest yayılma gigabayt megabayt yüzlerce ve yok bir performans açısından kritik alanda çalışmak az tercih yığılmasına. Çökmelerin tespit edilmesi ve çoğaltılması kolaydır, kullanıcının en sevdiği halde bile programcının en sevdiği türden bir hata haline gelir ve bu çökmelerin birçoğu kullanıcıya ulaşmadan önce aklı başında bir test prosedürü ortaya çıkar.
Neyse, bunlar GC ve manuel hafıza yönetimi arasındaki farklar. Anında sorunuzu yanıtlamak için, manuel bellek yönetiminin zor olduğunu söyleyebilirim, ancak sızıntılarla ilgisi çok az ve kaynak yönetimi önemsiz olduğunda hem GC hem de manuel bellek yönetimi biçimleri hala çok zor . GC, tartışmasız programın gayet iyi çalıştığı, ancak gittikçe daha fazla kaynak tükettiği durumlarda daha zor bir davranış sergiliyor. Manuel form daha az zor, ancak yukarıda gösterilen hatalar nedeniyle çok fazla zaman harcayacak ve çökecek.