Neden Java ve C gibi C + C ++ gibi dillerde çöp toplama yok? [kapalı]


57

Eh, C için malloc / free ve C ++ 'da hafıza yönetimi için new / use-a-destructor gibi şeyler olduğunu biliyorum, ancak kullanıcının bu dillere neden "yeni güncelleme" olmadığını merak ediyordum. belleği manuel olarak yönetme veya sistemin otomatik olarak yapması için seçeneğiniz var mı (çöp toplama)?

Biraz newb-ish sorusu, ancak sadece yaklaşık bir yıldır CS olmuştur.


9
Bu dönemde iPhone geliştirmede bir modül var. 2 yıl boyunca Android uygulamaları kodladıktan sonra, bu soru sınıfın çoğunu oldukça zorladı. Ancak şimdi Java'nın kaç saat boyunca kötü bellek yönetimi hatalarını izlememize ve kazan plakası kodu yazmamıza gerek kalmamasını görüyoruz.
siamii

7
@NullUserException, çünkü bir GC'yi hemen hemen ima eden belleği geri kazanmak için bir yol belirtmez.
Winston Ewert

1
@ bizso09: Henüz ARC'ye baktın mı? Referans sayımı için sistem desteğine sahip olduğunuzda yavaş / yağ / deterministik olmayan GC'ye gerek yok: developer.apple.com/technologies/ios5
JBRWilkinson

3
Bu oldukça güzel sorunun cevapları dini saçmalıklarla dolu.
abatishchev

1
C ve C ++ 'da bir işaretçi almak, int'ye almak ve bir sayı eklemek mümkündür. Daha sonra sayı int'den çıkartılır ve sonucu tekrar göstericiye aktarılır. Daha önce olduğu gibi aynı göstergeyi alacaksınız. Adresi sadece başka bir değere sahip olan değişkende saklanırken, bu hafızayı toplamayan bir GC'nin uygulanmasında iyi şanslar. Örnek aptal olduğunu biliyorum ama XOR bağlantılı bir liste benzer bir şey kullanıyor. Bunu bir cevap olarak gönderirdim ama soru kapandı.
Marian Spanik

Yanıtlar:


71

Çöp toplama, tahsislerin takibi ve / veya referans sayımı için veri yapıları gerektirir. Bunlar bellekte, performansta ve dilin karmaşıklığında ek yükler yaratır. C ++ "metale yakın" olmak üzere tasarlanmıştır, diğer bir deyişle, kolaylık özellikleriyle tradeoffun daha yüksek performans tarafını tutmaktadır. Diğer diller bu farklılığı farklılaştırır. Bu, tercih ettiğiniz vurguyu seçen bir dil seçiminde dikkat edilmesi gereken noktalardan biridir.

Bununla birlikte, C ++ 'da referans sayımı için oldukça hafif ve performans gösteren birçok şema var, ancak dilin bir parçası olmak yerine hem ticari hem de açık kaynak kütüphanelerde bulunuyorlar. Nesne ömrünü yönetmek için yapılan referans sayımı, çöp toplama işlemiyle aynı değildir, ancak aynı türden sorunların çoğuna yöneliktir ve C ++ 'nın temel yaklaşımına daha iyi uyar.


26
İkincil bir konu ise GC belirleyici değildir. Program "onu bıraktıktan" sonra nesnenin hafızasında olabilir veya olmayabilir. Geri sayım yaşam döngüleri son referans düştüğünde, bellek düştüğünde belirleyicidir. Bunun yalnızca bellek verimliliği için değil, aynı zamanda hata ayıklama için de etkileri vardır. Yaygın bir programlama hatası "zombi" nesnesidir, teorik olarak bırakılmış referans hafızasıdır. GC'nin bu etkiyi maskeleme olasılığı daha yüksektir ve aralıklı ve izlemesi oldukça zor olan böcekler üretir.
kylben

22
- modern gc'ler tahsisleri takip etmiyor veya referansları saymıyor. Şu anda yığındaki her şeyden bir grafik oluşturuyorlar ve her şeyi yoğunlaştırıp siliyorlar (basitleştirilmiş) ve GC normalde dil karmaşıklığının azalmasına neden oluyor . Performans avantajı bile sorgulanabilir.
Joel Coehoorn 09:11

13
Er, @kylben, otomatik GC'nin dilde pişirilmesinin asıl amacı, zombi nesnelerine referans vermenin imkansız hale gelmesidir , çünkü GC sadece referans vermesi mümkün olmayan nesneleri serbest bırakır! Manuel bellek yönetimi ile hata yaptığınız zaman bahsettiğiniz zor izleri alıyorsunuz.
Ben

14
-1, GC referansları saymaz. Ayrıca, bellek kullanımınıza ve ayırma düzeninize bağlı olarak, bir GC daha hızlı olabilir (bellek kullanımında bir ek yük ile). Yani performans hakkındaki argüman da yanlış. Sadece metale yakın olmak aslında geçerli bir nokta.
deadalnix

14
Ne Java, ne de C # referans sayımı kullanmaz: Referans saymaya dayanan GC şemaları karşılaştırma açısından oldukça ilkeldir ve modern çöp toplayıcılardan çok daha kötü performans gösterir (temel olarak referans kopyaladığınızda referans sayıları değiştirmek için bellek yazmaları gerekir çünkü!)
mikera

44

Açıkçası, C dilinde hiç bir hafıza yönetimi yoktur. malloc () ve free (), dilde anahtar kelimeler değil, yalnızca bir kitaplıktan çağrılan işlevlerdir. Malloc () ve free () C standart kütüphanesinin bir parçası olduğundan ve C'nin herhangi bir standart uyumlu uygulaması tarafından sağlanacağı için, bu ayrım şimdi bilgili olabilir.

Neden bellek yönetimi için standart olmayan bir dil istiyorsunuz? Bu, C'nin kökenlerine 'taşınabilir montaj' olarak geri döner. Özel bellek yönetimi tekniklerinden faydalanabilecek veya hatta gerektirebilecek birçok donanım ve algoritma vakası vardır. Bildiğim kadarıyla, Java'nın yerel bellek yönetimini tamamen devre dışı bırakmanın ve kendikiyle değiştirmenin bir yolu yok. Bazı yüksek performanslı / minimum kaynak durumlarında bu kabul edilemez. C, programınızın tam olarak hangi altyapıyı kullanacağını seçmek için neredeyse tamamen esneklik sağlar. Ödenen bedel, C dilin doğru, hatasız kod yazarken çok az yardım sağlamasıdır.


2
Genel olarak iyi bir cevap için bir tane +1, ama özellikle de "Ücretin bedeli C dilin doğru, hatasız kod yazarken çok az yardım sağlamasıdır"
Shivan Dragon,

2
C bellek yönetimi var - ama sadece çalışıyor, bu yüzden insanlar bunu fark etmiyorlar. Statik bellek, kayıtlar ve yığın var. Yığından ayrılmaya başlayana kadar, iyi ve zekisin. İşleri mahveten yığın tahsisi. Java gelince, herkes kendi Java çalışma zamanını yazabilir - "Sistemin Java'sı" olarak adlandırılabilecekler dahil, aralarından seçim yapabileceğiniz çok şey vardır. .NET, C'nin yapabileceği her şeyi yapabilir - yalnızca C ++ 'ın yerel özelliklerinin gerisinde kalır (örneğin, sınıflar yalnızca .NET'te yönetilir). Tabii ki, C ++ 'a sahip olan C ++' a sahip olan ve C ++ 'ın yaptığı her şeyi ve .NET' in yaptığı her şeyi.
Luaan

1
@Luaan "Hafıza yönetimine" sahip olmanın çok cömert bir tanımı olduğunu söyleyebilirim. "Yığından ayrılmaya başlayana kadar, iyisin ve zekisin. Bu şeyleri mahveten yığın tahsisidir" mükemmel derecede iyi bir uçak, sadece uçamıyor.
Charles E. Grant

1
@ CharlesE.Grant Tamamen işlevsel bir dil, bu tür bellek yönetimi ile her şeyi yapabilir. Yığın tahsisinin bazı kullanım durumlarında iyi bir takas olması, tüm diller / çalışma zamanları için bir kriter olduğu anlamına gelmez. Bellek yönetiminin “bellek yönetimi” olmayı bırakması gibi bir şey değil, çünkü basit, doğrudan ileri, sahnelerin arkasında gizli. Statik bellek tahsisini tasarlamak, hala yığın yönetimi ve diğer elinizde ne varsa, kullanımı iyi bir bellek yönetimidir.
Luaan

"herhangi bir standart uyumlu uygulama", yalnızca standart uyumlu ana bilgisayar ortamı uygulaması için doğru değildir. Bazı Platformlar / Standart Kütüphaneler, çoğu 8 veya 16 Bit gömülü Mikrodenetleyici için malloc()veya sağlamaz free(). (örnek PIC için MLAP-Derleyicileridir)
12431234123412341234123

32

Asıl cevap, güvenli ve verimli bir çöp toplama mekanizması oluşturmanın tek yolunun opak referanslar için dil düzeyinde desteğe sahip olmasıdır . (Ya da tam tersine, doğrudan bellek manipülasyonu için dil düzeyinde destek eksikliği .)

Java ve C #, değiştirilemeyen özel referans türlerine sahip olduklarından bunu yapabilir. Bu, çalışma zamanına yüksek performanslı bir GC uygulaması için çok önemli olan bellekteki ayrılmış nesneleri taşımak gibi şeyler yapma özgürlüğü verir .

Kayıt için, hiçbir modern GC uygulaması referans sayımı kullanmaz , bu tamamen kırmızı bir ringa balığıdır. Modern GC'ler, yeni tahsislerin temelde yığın tahsislerinin C ++ gibi bir dilde olduğu şekilde muamele edildiği ve daha sonra periyodik olarak hala canlı olan yeni tahsis edilen nesnelerin ayrı bir "kurtulan" alana ve tüm bir nesile taşındığı kuşak koleksiyonu kullanır. nesnelerin bir kerede serbest bırakılır.

Bu yaklaşımın avantajları ve dezavantajları vardır: Bunun tersi, GC'yi destekleyen bir dilde yığın tahsislerinin GC'yi desteklemeyen bir dilde yığın tahsisleri kadar hızlı olması ve olumsuz tarafı ise, tahrip edilmeden önce temizleme gerçekleştirmesi gereken nesnelerin de olmasıdır. ayrı bir mekanizma (örneğin, C # usinganahtar kelimesi) gerektirir veya temizleme kodları deterministik olmayan şekilde çalışır.

Yüksek performanslı bir GC'nin bir anahtarının, özel bir referans sınıfı için dil desteği olması gerektiğini unutmayın. C bu dil desteğine sahip değil ve asla olmayacak; C ++ operatörünün aşırı yüklenmesine sahip olduğundan, dikkatle yapılması gerekse de GC'd pointer tipini taklit edebilir. Aslında, Microsoft CLR (.NET çalışma zamanı) altında çalışacak olan C ++ lehçesini icat ettiğinde, Foo^onları "C ++ tarzı referanslar" dan ayırmak için "C # tarzı başvuruları" (örneğin ) için yeni bir sözdizimi icat etmek zorunda kaldılar. (örneğin Foo&).

C ++ 'ın sahip olduğu ve C ++ programcıları tarafından düzenli olarak kullanılan şey, gerçekten sadece referans sayma mekanizması olan akıllı işaretçilerdir . Referans sayımının "doğru" GC olduğunu düşünmezdim, ancak manuel bellek yönetiminden veya gerçek GC'den daha düşük performans karşılığında fakat aynı zamanda deterministik yıkım avantajıyla, aynı faydaların çoğunu sağlıyor.

Günün sonunda, cevap gerçekten bir dil tasarım özelliğine dayanıyor. C bir seçim yaptı, C ++, çoğu amaç için yeterince iyi alternatifler sunarken, C ile geriye dönük olarak uyumlu olmasını sağlayan bir seçim yaptı ve Java ve C #, C ile uyumlu olmayan ancak aynı zamanda yeterince iyi olan farklı bir seçim yaptı. çoğu amaç. Ne yazık ki, gümüş mermi yoktur, ancak farklı seçeneklere aşina olmak, şu anda oluşturmaya çalıştığınız program için doğru olanı seçmenize yardımcı olacaktır.


4
Bu sorunun asıl cevabı
coredump

1
C ++ bölümü için, bugünlerde std :: unique_ptr ve std :: move :) 'e bakmalısınız
Niclas Larsson

@NiclasLarsson: Amacını anladığımdan emin değilim. Bunun std::unique_ptr"opak referanslar için dil düzeyinde destek" olduğunu mu söylüyorsunuz ? (Kastettiğim desteğin tür değildi ve ben de doğrudan bellek manipülasyon için destek de C ++ çıkarıldı sürece yeterli olduğunu sanmıyorum.) Benim cevap akıllı işaretçileri söz, ve ben dikkate alacağını std:unique_ptrakıllı işaretçi , aslında referans sayımı yaptığı için, sadece referans sayısının sıfır veya bir olduğu özel durumları desteklemektedir (ve std::movereferans sayımı güncelleme mekanizmasıdır).
Daniel Pryden

std::unique_ptrreferans sayımı yoktur ve referanslarla std::movehiçbir ilgisi yoktur (yani "performans yok"). Ancak std::shared_ptrgörüşünüzü görüyorum, tıpkı tarafından güncellenen bir referans sayısının olduğu gibi std::move:)
Niclas Larsson

2
@ Mike76: Tahsisat tarafında, bir GC tahsisatçısı yığın tahsisi kadar hızlı bir şekilde çalışacak ve GC aynı anda binlerce nesneyi serbest bırakabilir. Bir geri sayım uygulamasıyla ne yaparsanız yapın, tahsis ve tahsisat asla mallocve den daha hızlı olamaz free. Yani evet, bir GC önemli ölçüde daha hızlı olabilir. ("Olabilir"
dediğime dikkat edin

27

Çünkü, C ++ 'ı kullanırken, gerek yoktur.

Herb Sutter: " Yıllardır silme yazmadım. "

bkz. Modern C ++ kodu yazma: C ++ yıllar içinde nasıl gelişti 21:10

Birçok deneyimli C ++ programcısını şaşırtabilir.


İlginç. Bugünkü okuma materyalim.
surfasb

Bah, bir video. Ama asla daha az, zaten ilginç.
surfasb

2
ilginç video 21 dakika içinde ve 55 dakika içinde en iyi bit idi. Çok kötü WinRT aramaları hala C ++ / CLI bumpf görünüyordu.
gbjbaanb

2
@ dan04: Bu doğru. Ama sonra, eğer C'ye yazarsan, istediğini elde edersin.
DeadMG

6
Akıllı işaretçileri yönetmek, çöp toplanan bir ortamda gereksiz referansların bulunmadığından emin olmaktan daha zorlu değildir. Çünkü GC aklınızı okuyamaz, bu da sihir değil.
Tamás Szelei 14:11

15

"Tüm" bir çöp toplayıcı, bellekte kayda değer bir nesne olup olmadığını ve silinip silinmediğini görmek için düzenli aralıklarla denetlenen bir işlemdir. (Evet, bunun çok büyük bir basitleştirme olduğunu biliyorum). Bu dilin bir özelliği değil, çerçevesidir.

- C ve C ++ için yazılmış çöp toplayıcılar vardır bu bir örnek.

Birinin dile "eklenmemesinin" bir nedeni, hafızayı yönetmek için kendi kodlarını kullandıkları için asla kullanmayacakları mevcut kodun büyüklüğü olabilir. Başka bir neden, C ve C ++ ile yazılmış uygulama türlerinin, bir çöp toplama işlemiyle ilişkili ek yüke ihtiyaç duymaması olabilir.


1
Ancak gelecek programlar çöp toplayıcıyı kullanmaya başlayacaktı, değil mi?
Karanlık Tapınak

5
Çöp toplama teorik olarak herhangi bir programlama dilden bağımsız olmasına rağmen, C / C ++ için yararlı bir GC yazmak oldukça zor ve hatta bir aptal olmayan bir tane yapmak bile imkansız (en azından Java'nınki gibi kusursuz) - Java'nın çekebilme nedeni kapalı, kontrollü bir sanallaştırılmış ortamda çalıştığı içindir. Tersine, Java dili GC için tasarlanmıştır ve GC yapmayan bir Java derleyicisini yazmakta zorlanacaksınız.
tdammers

4
@tdammers: Çöp toplama işleminin mümkün olması için dilin desteklenmesi gerektiğine katılıyorum. Ancak, asıl nokta sanallaştırma ve kontrol edilen ortam değil, katı yazmadır. C ve C ++ zayıf yazılmıştır, bu nedenle işaretçi tamsayı değişkeninde saklamak, işaretçileri ofsetlerden yeniden yapılandırmak ve toplayıcının ulaşılabilir olanı güvenilir bir şekilde söyleyebilmesini engelleyen şeyler yapmak gibi bir şeye izin verir (C ++ 11 en azından en azından izin vermesini yasaklar. muhafazakar koleksiyonerler). Java'da her zaman bir referansın ne olduğunu bilirsiniz, böylece yerel olarak derlenmiş olsa bile tam olarak toplayabilirsiniz.
Jan Hudec

2
@ ThorbjørnRavnAndersen: İşaretçileri, hiçbir çöp toplayıcısının bulamayacağı şekilde depolayan geçerli bir C programı yazabilirim. Daha sonra bir çöp toplayıcıyı takarsanız mallocve freedoğru programımı bozarsınız.
Ben Voigt

2
@ ThorbjørnRavnAndersen: Hayır, freebitinceye kadar arayamazdım . Ama açıkça söyleyene kadar hafızayı boşa vermeyen önerilen çöp toplayıcınız, freebir çöp toplayıcı değil.
Ben Voigt

12

Çöp toplama zorlukla bir seçenek olduğunda C bir çağda tasarlanmıştı. Ayrıca, çöp toplamanın genellikle işe yaramayacağı kullanımlar için de düşünülmüştür - çıplak metal, minimum bellek ve minimum çalışma zamanı desteği ile gerçek zamanlı ortamlar. C'nin, 64 * K * bayt belleğe sahip bir pdp-11'de çalışan ilk unix'in uygulama dili olduğunu unutmayın . C ++ başlangıçta C'nin bir uzantısıydı - seçim çoktan yapılmıştı ve çöp toplama işlemini mevcut bir dile çekmek çok zor. Zemin kattan inşa edilmesi gereken bir şey.


9

Kesin fiyat sözlerim yok ama hem Bjarne hem de Herb Sutter satırlar boyunca bir şeyler söylüyor:

C ++ çöp toplayıcıya ihtiyaç duymaz, çünkü çöp yoktur.

Modern C ++ 'da akıllı işaretçiler kullanırsınız ve bu nedenle çöp alamazsınız.


1
Akıllı işaretçiler nelerdir?
Karanlık Tapınak

11
Bu kadar basit olsaydı, hiç kimse herhangi bir GC uygulardı.
deadalnix

7
@deadalnix: Doğru, çünkü hiç kimse aşırı derecede karmaşık, yavaş, şişirilmiş veya gereksiz bir şey uygulamıyor. Tüm yazılımlar her zaman% 100 verimlidir, değil mi?
Zach,

5
@deadalnix - Bellek yönetimine C ++ yaklaşımı, çöp toplayıcılarından daha yenidir. RAII, C + + için Bjarne Stroustrup tarafından icat edildi. Yıkıcı temizliği daha eski bir fikir, ancak istisna güvenliğini sağlama kuralları anahtardır. Fikrin ilk ne zaman tam olarak ne zaman tanımlandığını bilmiyorum ama ilk C ++ standardı 1998'de sonlandırıldı ve Stroustrups "C ++ 'ın Tasarım ve Evrimi" 1994 yılına kadar yayınlanmadı ve istisnalar, C ++' a nispeten yeni bir katkı oldu. 1990'da "Açıklamalı C ++ Referans El Kitabı" nın yayınlanmasından sonra inanıyorum. GC 1959'da Lisp için icat edildi.
Steve314

1
@deadalnix - stil de ray akıllı işaretçi sınıfını kullanan - - doğrusu en az bir Java VM (neredeyse) C ++ kullanılarak uygulanabilecek bir referans sayma GC kullanılan biliyoruz çünkü o VM'lerini mevcut daha çok iş parçacıklı kodu için daha verimli oldu? Www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf adresini ziyaret edin. Bunu C ++ 'da pratikte görmemenizin bir nedeni, normal GC koleksiyonudur - döngüleri toplayabilir, ancak döngülerin varlığında güvenli bir yıkıcı sırasını seçemez ve bu nedenle güvenilir bir yıkıcı temizliği sağlayamaz.
Steve314

8

Bu dillerin neden isteğe bağlı bir çöp toplayıcı içerecek şekilde güncellenmediğini soruyorsunuz.

İsteğe bağlı çöp toplama işlemindeki sorun, farklı modelleri kullanan kodu karıştıramaz olmanızdır. Yani, bir çöp toplayıcı kullandığınızı varsayan bir kod yazarsam, programınızda çöp toplama özelliği kapalı olan bir programı kullanamazsınız. Bunu yaparsan her yere sızacak.


6

Aygıt işleyicisini çöp toplama dilinde bir dilde yazmayı hayal edebiliyor musunuz? GC çalışırken hattan kaç parça geçebilir?

Veya bir işletim sistemi? Çekirdeğe başlamadan önce çöp toplama işlemini nasıl başlatabilirsiniz?

C, donanım görevlerine yakın düşük seviye için tasarlanmıştır. Sorun? Bu kadar hoş bir dil mi ki, birçok üst düzey görev için de iyi bir seçim. Dil çekleri bu kullanımların farkındadır, ancak öncelikli olarak aygıt sürücülerinin, gömülü kodların ve işletim sistemlerinin gereksinimlerini desteklemeleri gerekir.


2
C yüksek seviye için iyi mi? İçkimi klavyemin her yerine taradım.
DeadMG

5
"Çok daha üst düzey görevler" dedi. O olabilir (... Birçok bir, iki,) trol sayma olabilir. Ve aslında ondan daha yüksek olduğunu söylemedi. Şakalar bir yana, olsa da, bu doğru - kanıt birçok önemli üst düzey projeler olduğunu varlık var başarıyla bu projelerin bir sürü için şimdi daha iyi seçimler olabilir C. geliştirilmiştir, ancak bir çalışma projesi Neymiş hakkında spekülasyon daha güçlü kanıtıdır olmuştur.
Steve314

Bazı yönetilen işletim sistemleri var ve oldukça iyi çalışıyorlar. Aslında, tüm sistemi yönettiğinizde, yönetilen kod kullanmanın getirdiği performans , gerçek hayat senaryolarında yönetilmeyen koddan daha hızlı , daha da düşüktür. Tabii ki, bunların hepsi "araştırma işletim sistemi" dir - yönetilen işletim sistemi içinde tamamen sanallaştırılmış bir yönetimsiz işletim sistemi yapmanın yanı sıra mevcut yönetilmeyen kodlarla uyumlu hale getirmelerinin bir yolu yoktur. Microsoft, bir noktada Windows Server'ı, bunlardan biriyle değiştirebileceklerini söyledi, ancak daha fazla sunucu kodu .NET'te yazıldığı için.
Luaan

6

Bu sorunun kısa ve sıkıcı cevabı, çöp toplayıcıları yazan insanlar için dışarıda toplanmamış bir dil olması gerektiğidir. Aynı anda bellek düzeni üzerinde çok hassas kontrol etme olanağı sunan bir dil olması kavramsal kolay değil ve üstünde çalışan bir GC vardır.

Diğer soru, neden C ve C ++ 'nın çöp toplayıcıları olmadığıdır. Şey, C ++ 'in çevrelerinde bir çiftinin olduğunu biliyorum, ancak gerçekten popüler değiller çünkü ilk etapta GC-ed için tasarlanmamış bir dille ve hala C ++' ı kullanan insanları kullanmak zorunda kalıyorlar. Bu yaş gerçekten bir GC özlüyor tür değil.

Ayrıca, eski bir GC-ed olmayan dile bir GC eklemek yerine, bir GC'yi desteklerken aynı sözdizimine sahip yeni bir dil oluşturmak daha kolaydır. Java ve C # bunun güzel örnekleridir.


1
Programers.se veya SO'da bir yerlerde, birisinin kendi kendine önyüklenen çöp toplanan bir şey üzerinde çalıştığını iddia eden bir iddia var - IIRC, temel olarak VM'yi GC dilini uygulamak için kullanılan bir önyükleme alt kümesiyle birlikte bir GC dili kullanarak uygulamak. İsmini unuttum. İçine baktığımda, temel olarak GC'siz alt-alttan çalışma-GC seviyesine sıçramayacakları ortaya çıktı. Bu ise prensipte mümkün ama pratikte hiçbir zaman ulaşılamamıştır AFAIK - kesinlikle şeyler zor yoldan yapmanın bir vaka.
Steve314

@ Steve314: Nerede bulduğunuzu hatırlarsanız bunu görmek isterim!
hugomg

buldum! Klein VM'ye atıfta bulunan stackoverflow.com/questions/3317329/… adresindeki yorumlara bakın . Sorunun bir kısmı onu bulma - soru kapatıldı.
Steve314

BTW - Ben yorumlarımı @missingno ile başlatamıyorum gibi görünüyor - ne veriyor?
Steve314

@ steve314: Bu konunun ekli olduğu cevabı ıskaladıktan sonra, zaten tüm yorumlar için bir bildirim aldım. Bu durumda @ -post yapmak gereksiz olabilir ve SE tarafından izin verilmez ( neden olsa da bana sorma ). (Gerçekte asıl sebep, numaramın eksik olması nedeniyle)
hugomg

5

Dahil olmak üzere çeşitli konular var ...

  • GC, C ++ 'dan önce ve muhtemelen C' den önce icat edilmiş olmasına rağmen, hem C hem de C ++, GC'ler yaygın olarak pratik olarak kabul edilmeden önce uygulanmıştır.
  • GC dilini ve platformunu, GC olmayan bir dil olmadan kolayca uygulayamazsınız.
  • Her ne kadar GC, tipik zaman çizelgelerinde vb. Geliştirilen tipik uygulama kodları için GC'den belirgin bir şekilde daha etkili olsa da, daha fazla geliştirme çabasının iyi bir denge olduğu ve özel bellek yönetiminin genel amaçlı bir GC'den daha iyi performans göstereceği durumlar vardır. Ayrıca, C ++ herhangi bir ilave geliştirme çabası olmasa da, çoğu GC dilden daha belirgindir.
  • GC, evrensel olarak C ++ tarzı RAII'den daha güvenli değildir. RAII, hafıza dışındaki kaynakların otomatik olarak temizlenmesini sağlar, çünkü güvenilir ve zamanında yıkıcıları destekler. Bunlar, referans çevrimleriyle ilgili sorunlar nedeniyle geleneksel GC yöntemleriyle birleştirilemez.
  • GC dillerinin kendine has karakteristik bellek sızıntıları vardır, özellikle bir daha asla kullanılamayacak olan, ancak hiçbir zaman boş bırakılmamış veya üzerine yazılmamış mevcut referansların bulunduğu yerlerde. Bunu açıkça yapma gereği, prensipte ihtiyaç deleteveya freeaçıkça gerekliliğinden farklı değildir . GC yaklaşımının hala bir avantajı var - sarkan referanslar yok - ve statik analiz bazı vakaları yakalayabilir, ancak yine de, tüm durumlar için mükemmel bir çözüm yoktur.

Temel olarak, kısmen dillerin yaşıyla ilgili, ancak her zaman GC olmayan diller için de bir yer olacak - biraz zor olsa bile. Ve cidden, C ++ 'ta GC eksikliği çok da önemli değil - hafızanız farklı şekilde yönetiliyor ama yönetilemiyor.

Microsofts tarafından yönetilen C ++ aynı uygulamada GC ve GC olmayanları bir araya getirme kabiliyetine sahiptir, her birinin avantajlarını karıştırıp eşleştirmeye izin verir, ancak bunun pratikte ne kadar iyi çalıştığını söyleme deneyimim yok.

Rep-whoring’in ilgili cevaplarına bağlantılar ...


4

Çöp toplama işlemi temelde DMA özellikli donanım için sürücü geliştirmek için kullanılan bir sistem dili ile uyumlu değildir.

Bir nesneye tek işaretçinin bazı çevre birimlerindeki bir donanım kaydında saklanması tamamen mümkündür. Çöp toplayıcı bunu bilmediğinden, nesneye erişilemez olduğunu ve topladığını düşünürdü.

Bu argüman GC'yi sıkıştırmak için iki katı tutar. Donanım çevre birimleri tarafından kullanılan nesnelere bellekte yapılan referansları korumaya özen gösterseniz bile, GC nesneyi yeniden konumlandırdığında, çevresel yapılandırma kaydında bulunan işaretçinin nasıl güncelleneceğini bilemez.

Bu nedenle, artık hareketsiz DMA tamponları ve GC yönetimli nesnelerin bir karışımına ihtiyacınız olacak, bu da her ikisinin de dezavantajlarına sahip olacağınız anlamına geliyor.


Muhtemelen her iki dezavantajın tüm dezavantajları, ancak her bir dezavantaj örneği daha düşüktür ve avantajlar için aynıdır. Açıkça anlaşılması gereken daha fazla bellek yönetimi türüne sahip olmanın karmaşıklığı vardır, ancak kodunuzdaki her kurs için doğru atı seçerek de önlenebilir. Muhtemelen, hayal ediyorum, ama orada teorik bir boşluk var. GC ve GC olmayanları daha önce aynı dilde karıştırmayı düşündüm, ancak aygıt sürücülerinde değil - daha çok GC uygulamasına sahip olmakla birlikte, bazı el ile bellek tarafından yönetilen düşük seviye veri yapısı kitaplıklarıyla.
Steve314

@ Steve314: Hangi nesnelerin manuel olarak serbest bırakılması gerektiğini hatırlamanın her şeyi serbest bırakmayı hatırlamak kadar zahmetli olduğunu söylemez miydiniz? (Tabii ki, akıllı işaretçiler de ikisine de yardımcı olabilir, bu yüzden ikisi de büyük bir sorun değil) Ve elle toplanan / sıkıştırılabilir nesnelere karşı elle yönetilen nesneler için farklı havuzlara ihtiyacınız var, çünkü sıkıştırma, dağılmış sabit nesneler olduğunda iyi çalışmaz. Yani hiçbir şey için çok fazla karmaşıklık.
Ben Voigt

2
Hepsi GC olan yüksek seviye kodu ile GC’yi seçen düşük seviye kodu arasında net bir ayrım varsa. Bu fikri temel olarak birkaç yıl önce D'ye bakarken, GC'den vazgeçmenize izin veren ancak geri dönmenize izin vermeyen bir fikir geliştirdim. Örneğin bir B + ağaç kütüphanesi alın. Bir bütün olarak kabın GC olması gerekir, ancak veri yapısı düğümleri büyük olasılıkla olmasa da - yaprak düğümleri üzerinden özelleştirilmiş bir tarama yapmak, GC'yi dal düğümleri arasında tekrarlı bir arama yapmaktan daha etkilidir. Bununla birlikte, bu taramanın içerdiği öğeleri GC'ye bildirmesi gerekir.
Steve314

Mesele şu ki, içerdiği bir işlevsellik parçası. B + ağaç düğümlerini özel WRT bellek yönetimi olarak ele almak, onları özel WRT olarak B + ağaç düğümleri olarak ele almaktan farklı değildir . Kapsüllenmiş bir kütüphanedir ve uygulama kodunun, GC davranışının atlandığını / özel kasaya sahip olduğunu bilmesi gerekmez. Bunun dışında, en azından o zamanlar D'de imkansızdı - dediğim gibi, içerilen öğeleri geri çekip GC'yi potansiyel GC kökleri olarak rapor etmenin bir yolu yok.
Steve314

3

Çünkü C & C ++, genel amaçlı, örneğin, gc ile boşa harcayamayacak kadar gömülü bir sistemde 1 MB belleğe sahip 16 bit işlemcide çalışmak için bile olsa, nispeten düşük seviyeli dillerdir.


1
"Yerleşik sistem"? C zamanında standardize edildi (1989), 1 MB belleğe sahip PC'leri kullanabilmeliydi .
dan04,

Katılıyorum, daha güncel bir örnek alıntı yapıyordum.
Petruza

1 MB ??? Kutsal schmoley, kim bu kadar RAM'e ihtiyaç duyacak? </billGates>
Mark K Cowan

2

Orada C ++ ve C bu C nasıl çalıştığını emin çöp toplayıcıları, ancak C yararlanabileceğiniz ++ RTTI dinamik nesne grafiği keşfetmek ve çöp toplama için bunu kullanmak.

Bildiğim kadarıyla, çöp toplayıcı olmadan Java yazamazsınız. Biraz arama geldi bu .

Java ve C / C ++ arasındaki temel fark, C / C ++ 'da seçimin daima sizin olmasıdır; oysa Java'da sık sık tasarım seçeneklerine gerek kalmadan kalıyorsunuz.


Ayrıca, özel çöp toplayıcıların daha iyi uygulandığını, daha verimli ve dile daha iyi uyduğunu. :)
Maksimum

Hayır, C / C ++ 'da nesne grafiğini dinamik olarak bulmak için RTTI kullanamazsınız: Her şeyi bozan düz eski veri nesneleridir. Bir çöp toplayıcısının o nesne içindeki işaretçiler ile işaretçiler arasında ayrım yapmasına izin verecek düz eski bir veri nesnesinde saklanan herhangi bir RTTI bilgisi yoktur. Daha da kötüsü, işaretçilerin tüm donanımlar üzerinde mükemmel bir şekilde hizalanması gerekmez, bu nedenle, 16 baytlık bir nesne verildiğinde, sadece iki tanesi üst üste binmeyen, 64 bitlik bir işaretçinin depolanabileceği 9 olası konum vardır.
cmaster

2

Performans ve güvenlik arasında bir takas.

Çöpünüzün Java'da toplanacağının garantisi yoktur, bu nedenle uzun süre boş alan kullanmakta beklenirken, referans alınmamış nesnelerin taranması (örneğin çöp), kullanılmayan bir nesneyi açıkça silmekten veya serbest bırakmaktan daha uzun sürer.

Bunun avantajı, elbette, bir işaretçi veya bellek sızıntısı olmayan bir dil oluşturabilmesidir, bu yüzden doğru kod üretme olasılığı daha yüksektir.

Bu tartışmaların bazen hafif bir 'dini' sınırı olabilir - uyarılmalıdır!


1

İşte C gibi bir sistem dilinde kullanılamaz yapan GC'nin içsel problemlerinin bir listesi:

  • GC, nesnelerini yönettiği kod seviyesinin altında çalışmalıdır. Çekirdekte böyle bir seviye yoktur.

  • Bir GC zaman zaman yönetilen kodu durdurmalıdır. Şimdi bunu çekirdeğinize yaparsanız ne olacağını düşünün. Makinenizdeki tüm işlemler, örneğin bir milisaniye için durdurulurken, GC mevcut tüm hafıza tahsislerini tarar. Bu, gerçek zamanlı olarak katı şartlar altında çalışan sistemler oluşturma girişimlerini öldürür.

  • Bir GC, işaretçilerle işaretçiler olmayanları ayırt edebilmelidir. Yani, var olan her bellek nesnesine bakabilmeli ve işaretçilerinin bulunabileceği bir ofset listesi üretebilmelidir.

    Bu keşif mükemmel olmalı: GC, keşfettiği tüm işaretçileri kovalayabilmelidir. Yanlış bir pozitif kabul ederse, muhtemelen çökecektir. Yanlış bir negatif saptamazsa, halen kullanımda olan, yönetilen kodu çökerten veya verilerini sessizce bozan bir nesneyi imha etmesi olasıdır.

    Bu kesinlikle tür bilgisinin var olan her bir nesnede saklanmasını gerektirir. Bununla birlikte, hem C hem de C ++, tür bilgisi içermeyen düz eski veri nesnelerine izin verir.

  • GC, doğası gereği yavaş bir iştir. Java ile sosyalleştirilmiş programcılar bunu fark etmeyebilirler, ancak programlar Java'da kullanılmadığında daha hızlı olabilirler. Java'yı yavaşlatan faktörlerden biri de GC. Java gibi GCed dillerinin süper hesaplamada kullanılmasını engelleyen şey budur. Makineniz yılda bir milyon elektrik tüketimine mal olursa, çöp toplama için bunun% 10'unu bile ödemek istemezsiniz.

C ve C ++, tüm olası kullanım durumlarını desteklemek için oluşturulan dillerdir. Ve gördüğünüz gibi, bu kullanım durumlarının birçoğu çöp toplama işlemi tarafından engelleniyor. Bu nedenle, bu kullanım durumlarını desteklemek için, C / C ++ çöp toplanamaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.