Reacties
- We ' hebben dit semester een module voor iPhone-ontwikkeling. Na twee jaar lang apps voor Android te hebben gecodeerd, raakte deze vraag de meeste van de klas behoorlijk hard. Nu pas zien we hoeveel uur Java ons daadwerkelijk heeft bespaard doordat we geen vervelende geheugenbeheerfouten hoeven op te sporen en geen boiler plate-code hoeven te schrijven.
- @NullUserException, aangezien het niet ' specificeer geen manier om geheugen terug te winnen die zo ongeveer een GC impliceert.
- @ bizso09: Heb je ARC al bekeken? Geen behoefte aan langzame / vette / niet-deterministische GC wanneer u ' systeemondersteuning hebt gekregen voor het tellen van referenties: developer.apple. com / technologies / ios5
- De antwoorden op deze redelijk goede vraag zitten vol religieuze onzin.
- In C en C ++ is het mogelijk om een aanwijzer te nemen, deze te casten naar int en voeg er een nummer aan toe. Trek later het getal af van de int en werp het resultaat terug naar een pointer. U krijgt dezelfde aanwijzer als voorheen. Veel succes met het implementeren van een GC die dat geheugen NIET verzamelt terwijl het adres alleen wordt opgeslagen in de variabele die ook een andere waarde heeft. Ik weet dat het voorbeeld belachelijk is, maar een XOR gekoppelde lijst gebruikt iets soortgelijks. Ik zou dit als antwoord plaatsen, maar de vraag is gesloten.
Answer
Garbage collection vereist datastructuren voor het volgen van toewijzingen en / of het tellen van referenties. Deze creëren overhead in het geheugen, de prestaties en de complexiteit van de taal. C ++ is ontworpen om “dicht bij het metaal” te zijn, met andere woorden, het neemt de hogere prestatiekant van de afweging versus gemakskenmerken. Andere talen maken die afweging anders. Dit is een van de overwegingen bij het kiezen van een taal, waaraan u de voorkeur geeft.
Dat gezegd hebbende, er zijn veel schemas voor het tellen van referenties in C ++ die redelijk licht en performant zijn, maar ze bevinden zich in bibliotheken, zowel commercieel als open source, in plaats van een deel van de taal zelf. Het tellen van referenties om de levensduur van objecten te beheren is niet hetzelfde als garbage collection, maar het pakt veel van dezelfde soorten problemen aan en past beter bij de basisbenadering van C ++.
Opmerkingen
- Een secundair probleem is dat de GC niet-deterministisch is. Het object kan zich al dan niet nog in het geheugen bevinden lang nadat het programma " heeft verwijderd " it. Refcount-levenscycli zijn deterministisch, wanneer de laatste referentie wordt verwijderd, wordt het geheugen verwijderd. Dit heeft niet alleen gevolgen voor de geheugenefficiëntie, maar ook voor het debuggen. Een veelvoorkomende programmeerfout is het " zombie " -object, referentiegeheugen dat theoretisch is verwijderd. GC maskeert dit effect veel waarschijnlijker en produceert bugs die zijn intermitterend en uiterst moeilijk op te sporen.
- – modern gc ' s volgen geen toewijzingen of tellen geen referenties. Ze bouwen een grafiek van vooravond Alles wat momenteel op de stapel staat en gewoon condenseren en al het andere wissen (vereenvoudigd), en GC resulteert normaal gesproken in verminderde taalcomplexiteit. Zelfs het prestatievoordeel is twijfelachtig.
- Eh, @kylben, het hele punt van automatische GC ingebakken in de taal is dat het onmogelijk wordt om naar zombie-objecten te verwijzen, omdat de GC maakt alleen objecten vrij die onmogelijk te verwijzen zijn! Je krijgt het soort moeilijk op te sporen bugs waar je ' over praat als je fouten maakt met handmatig geheugenbeheer.
- -1, GC telt niet mee referenties. Bovendien, afhankelijk van uw geheugengebruik en toewijzingsschema, kan een GC sneller zijn (met een overhead in geheugengebruik). Dus het argument over prestatie is ook een misvatting. Alleen het dicht bij het metaal is eigenlijk een geldig punt.
- Noch Java noch C # gebruiken referentietelling: GC-schemas gebaseerd op referentietelling zijn in vergelijking vrij primitief en presteren veel slechter dan moderne garbage collectors (voornamelijk omdat ze moet geheugen schrijven om referentietellingen te wijzigen telkens wanneer u een referentie kopieert!)
Antwoord
Strikt genomen, er is helemaal geen geheugenbeheer in de C-taal. malloc () en free () zijn geen sleutelwoorden in de taal, maar alleen functies die worden aangeroepen vanuit een bibliotheek.Dit onderscheid is nu misschien pedant, omdat malloc () en free () deel uitmaken van de C-standaardbibliotheek, en wordt geleverd door elke standaardconforme implementatie van C, maar dit was in het verleden niet altijd waar.
Waarom zou je een taal willen zonder standaard voor geheugenbeheer? Dit gaat terug naar de oorsprong van C als “draagbare assemblage”. Er zijn veel gevallen van hardware en algoritmen die kunnen profiteren van, of zelfs behoefte hebben aan, gespecialiseerde geheugenbeheertechnieken. Voor zover ik weet, is er geen manier om het native geheugenbeheer van Java volledig uit te schakelen en te vervangen door het uwe. Dit is gewoon niet acceptabel in sommige situaties met hoge prestaties / minimale resources. C biedt bijna volledige flexibiliteit om precies te kiezen welke infrastructuur je programma gaat gebruiken. De betaalde prijs is dat de C-taal erg weinig hulp biedt bij het schrijven van correcte, foutvrije code.
Opmerkingen
- +1 een voor het algemeen goede antwoord, maar ook speciaal voor " De betaalde prijs is dat de C-taal zeer weinig hulp biedt bij het schrijven van de juiste, foutvrije code "
- C heeft geheugenbeheer, maar het werkt gewoon, dus mensen merken het nauwelijks. Daar ' s statische geheugen, registers en de stapel. Totdat je begint met toewijzen buiten de heap, ben je ' prima en dandy. Het is ' de toewijzing van de hoop die dingen verprutst . Zoals voor Java kan iedereen zijn eigen Java-runtime schrijven – er is ' genoeg om uit te kiezen, inclusief wat genoemd zou kunnen worden " Systeem ' s Java ". .NET kan vrijwel alles doen wat C kan – het blijft alleen achter bij de native mogelijkheden van C ++ ' (klassen worden bijvoorbeeld alleen beheerd in .NET). Je hebt natuurlijk ook C ++. NET, dat alles heeft wat C ++ doet en alles .NET doet.
- @Luaan I ' d zeg dat ' is een zeer genereuze definitie van " geheugenbeheer " " Totdat je begint met toewijzen uit de hoop, ben je ' prima en dandy. Het ' is de heap-toewijzing die dingen verprutst ", dat ' is als zeggen een auto is een prima vliegtuig, het is gewoon niet ' in staat om te vliegen.
- @ CharlesE.Grant Nou, een puur functionele taal kan daar alles mee soort geheugenbeheer. Alleen omdat heap-toewijzing in sommige gevallen een goede afweging is, betekent ' niet dat het ' de benchmark is voor alle talen / runtimes . Het ' is niet zoals geheugenbeheer niet langer " geheugenbeheer " alleen omdat het ' s eenvoudig, ongecompliceerd, verborgen achter de schermen. Het ontwerpen van statische geheugentoewijzing is nog steeds geheugenbeheer, evenals een goed gebruik van de stapel en al het andere dat je beschikbaar hebt.
- " elke standaard-compatibele implementatie " is niet waar, alleen voor implementatie van een standaard compatibele hostomgeving. Sommige platforms / standaardbibliotheken, de meeste voor 8 of 16-bits embedded microcontroller, bieden geen
malloc()
offree()
. (voorbeeld zijn MLAP-Compilers voor PIC)
Answer
Het echte antwoord is dat de enige manier om een veilig, efficiënt garbage collection-mechanisme is om ondersteuning op taalniveau te hebben voor ondoorzichtige verwijzingen. (Of, omgekeerd, een gebrek aan ondersteuning op taalniveau voor directe geheugenmanipulatie.)
Java en C # kunnen het omdat ze speciale referentietypes hebben die niet kunnen worden gemanipuleerd. Dit geeft de runtime de vrijheid om dingen te doen als verplaats toegewezen objecten in het geheugen , wat cruciaal is voor een krachtige GC-implementatie .
Voor de goede orde, geen enkele moderne GC-implementatie gebruikt referentietelling , dus dat is helemaal rood haring. Moderne GCs gebruiken een generatieverzameling, waarbij nieuwe toewijzingen in wezen op dezelfde manier worden behandeld als stacktoewijzingen in een taal als C ++, en vervolgens worden alle nieuw toegewezen objecten die nog in leven zijn, periodiek verplaatst naar een aparte overlevingsruimte en een hele generatie van objecten wordt meteen ongedaan gemaakt.
Deze benadering heeft voor- en nadelen: het voordeel is dat heap-toewijzingen in een taal die GC ondersteunt zo snel zijn als stack-toewijzingen in een taal die GC niet ondersteunt, en het nadeel is dat objecten die moeten worden opgeschoond voordat ze worden vernietigd, ofwel een afzonderlijk mechanisme nodig hebben (bijv. C #” s using
trefwoord), anders werkt hun opschoningscode niet-deterministisch.
Merk op dat een sleutel tot een krachtige GC is dat er taalondersteuning moet zijn voor een speciale klasse van referenties. C heeft deze taalondersteuning niet en zal dat ook nooit doen; omdat C ++ overbelasting door de operator heeft, zou het een GC “d pointer-type kunnen emuleren, hoewel het voorzichtig zou moeten gebeuren. Toen Microsoft hun dialect C ++ uitvond dat zou draaien onder de CLR (de .NET-runtime), moesten ze een nieuwe syntaxis bedenken voor “C # -stijlverwijzingen” (bijv. Foo^
) om ze te onderscheiden van “C ++ – stijlreferenties” (bijv. Foo&
).
Wat C ++ wel heeft, en wat regelmatig wordt gebruikt door C ++ programmeurs, is slimme wijzers , die eigenlijk slechts een mechanisme voor het tellen van referenties zijn. Ik zou referentietelling niet als “waar” GC beschouwen, maar het biedt veel van dezelfde voordelen, ten koste van langzamere prestaties dan handmatig geheugenbeheer of echte GC, maar met het voordeel van deterministische vernietiging.
Uiteindelijk komt het antwoord eigenlijk neer op een taalontwerpfunctie. C heeft één keuze gemaakt, C ++ heeft een keuze gemaakt waardoor het achterwaarts compatibel is met C en toch alternatieven biedt die goed genoeg zijn voor voor de meeste doeleinden, en Java en C # hebben een andere keuze gemaakt die niet compatibel is met C, maar ook goed genoeg is voor de meeste doeleinden. Helaas is er geen wondermiddel, maar als je bekend bent met de verschillende keuzes die er zijn, kun je de juiste kiezen voor welk programma dan ook dat je momenteel probeert te bouwen.
Reacties
- Dit is het daadwerkelijke antwoord op de vraag
- Voor het c ++ deel, tegenwoordig zou je moeten kijken naar std :: unique_ptr en std :: move 🙂
- geen moderne GC implem entation gebruikt referentietelling : cPython gebruikt zowel referentietelling als automatische verzameling .
- @ Mike76: Aan de toewijzingskant werkt een GC-allocator ongeveer net zo snel als stack-allocatie, en de GC kan duizenden objecten tegelijkertijd ongedaan maken. Wat u ook doet met een implementatie voor ref-counting, toewijzing en ongedaan maken van toewijzing zullen nooit sneller zijn dan
malloc
enfree
. Dus ja, een GC kan aanzienlijk sneller zijn. (Merk op dat ik zei dat " " kan zijn – natuurlijk wordt de exacte prestatie van elk programma door veel factoren beïnvloed.) - geen enkele moderne GC-implementatie gebruikt referentietelling Swift gebruikt automatische referentietelling.
Antwoord
Omdat het niet nodig is om de kracht van C ++ te gebruiken.
Herb Sutter:” Ik “heb” in geen jaren “delete” geschreven. ”
zie Moderne C ++ -code schrijven: hoe C ++ zich in de loop der jaren heeft ontwikkeld 21:10
Het kan velen verbazen ervaren C ++ programmeurs.
Reacties
- Interessant. Mijn leesmateriaal voor vandaag.
- Bah, een video. Maar toch, al interessant.
- interessante video. 21 minuten en 55 minuten waren de beste dingen. Jammer dat de WinRT-aanroepen er nog steeds uitzagen als C ++ / CLI bumpf.
- @ dan04: Dat ' is waar. Maar als je in C schrijft, krijg je waar je om vraagt.
- Het beheren van de slimme tips is niet veeleisender dan ervoor zorgen dat je ' t onnodige referenties hebben in een garbagecollection-omgeving. Omdat GC ' je gedachten niet kan lezen, is het ' ook geen magie.
Answer
“All” een garbage collector is een proces dat periodiek wordt uitgevoerd om te zien of er objecten in het geheugen zonder referentie zijn en of ze worden verwijderd. (Ja, ik weet dat dit een grove oversimplificatie is). Dit is geen eigenschap van de taal, maar van het framework.
Er zijn garbage collectors geschreven voor C en C ++ – deze bijvoorbeeld .
Een reden waarom iemand niet “is” toegevoegd aan de taal zou kunnen zijn vanwege de enorme hoeveelheid bestaande code die deze nooit zou gebruiken omdat ze hun eigen code gebruiken om het geheugen te beheren. Een andere reden zou kunnen zijn maar de soorten applicaties die zijn geschreven in C en C ++ hebben niet de overhead nodig die gepaard gaat met een garbage collection-proces.
Opmerkingen
- Maar toekomstige programmas geschreven zou de garbage collector gaan gebruiken, niet?
- Hoewel garbage collection theoretisch onafhankelijk is van welke programmeertaal dan ook, is het vrij moeilijk om een bruikbare GC voor C / C ++ te schrijven, en zelfs onmogelijk om een onfeilbare te maken (minstens zo onfeilbaar als Java ' s) – de reden dat Java het voor elkaar kan krijgen, is omdat het in een gecontroleerde gevirtualiseerde omgeving draait. Omgekeerd is de Java-taal ontworpen voor GC, en u ' zult het moeilijk hebben om een Java-compiler te schrijven die niet ' doet GC .
- @tdammers: ik ben het ermee eens dat garbage-collection ondersteund moet worden door de taal om mogelijk te zijn. Het belangrijkste punt is echter niet virtualisatie en gecontroleerde omgeving, maar strikt typen. C en C ++ zijn zwak getypt, dus ze laten dingen toe als het opslaan van de pointer in integer-variabele, het reconstrueren van pointers van offsets en dergelijke dingen die voorkomen dat de verzamelaar betrouwbaar kan vertellen wat bereikbaar is (C ++ 11 verbiedt de laatste om ten minste conservatieve verzamelaars). In Java weet je altijd wat een referentie is, dus je kunt het precies verzamelen, zelfs als het is gecompileerd naar native.
- @Thorbj ø rnRavnAndersen: Ik kan een geldig C-programma dat verwijzingen zo opslaat dat geen enkele garbage collector ze ooit zou kunnen vinden. Als je vervolgens een garbage collector aan
malloc
enfree
koppelt, zou je mijn correcte programma breken. - @Thorbj ø rnRavnAndersen: Nee, ik zou ' niet
free
bellen totdat ik er klaar mee was . Maar je voorgestelde garbage collector die het geheugen niet ' vrijmaakt totdat ik explicietfree
aanroep isn ' ta garbage collector.
Answer
C is ontworpen in een tijdperk waarin garbage collection nog maar net was een optie. Het was ook bedoeld voor toepassingen waar garbage collection over het algemeen niet zou werken – bare metal, real-time omgevingen met minimaal geheugen en minimale runtime-ondersteuning. Onthoud dat C de implementatietaal was voor de eerste unix, die draaide op een pdp-11 met 64 * K * bytes geheugen. C ++ was oorspronkelijk een uitbreiding op C – de keuze was al gemaakt, en het is erg moeilijk om garbage collection op een bestaande taal te enten. Het is iets dat vanaf de begane grond moet worden ingebouwd.
Answer
Ik heb niet de exacte aanhalingstekens, maar zowel Bjarne als Herb Sutter zeggen iets in de trant van:
C ++ heeft geen “garbage collector” nodig, omdat het geen afval heeft.
In moderne C ++ je gebruikt slimme aanwijzingen en hebt daarom geen rotzooi.
Opmerkingen
- wat zijn slimme aanwijzingen?
- als dat het was simpel, niemand zou een GC hebben geïmplementeerd.
- @deadalnix: Juist, want niemand implementeert ooit iets overdreven gecompliceerd, traag, opgeblazen of onnodig. Alle software is altijd 100% efficiënt, toch?
- @deadalnix – De C ++ – benadering van geheugenbeheer is nieuwer dan garbage collectors. RAII is uitgevonden door Bjarne Stroustrup voor C ++. Destructor-opruiming is een ouder idee, maar de regels voor het waarborgen van uitzonderingsveiligheid zijn essentieel. Ik weet niet ' wanneer precies wanneer het idee zelf voor het eerst werd beschreven, maar de eerste C ++ -standaard werd in 1998 afgerond, en Stroustrups " Design en evolutie van C ++ " werd niet ' t gepubliceerd tot 1994, en uitzonderingen waren een relatief recente toevoeging aan C ++ – na de publicatie van de " Geannoteerde C ++ Referentiehandleiding " in 1990, geloof ik. GC werd in 1959 uitgevonden voor Lisp.
- @deadalnix – weet u dat ten minste één Java-VM een referentietellende GC gebruikte die (bijna) kon worden geïmplementeerd met C ++ – stijl RAII met behulp van een slimme pointerklasse – precies omdat het efficiënter was voor multithreaded code dan bestaande VMs? Zie www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf. Een reden waarom u dit in de praktijk niet ' niet ziet in C ++, is de gebruikelijke GC-verzameling – deze kan cycli verzamelen, maar ' niet kiezen een veilige vernietigingsopdracht in de aanwezigheid van cycli, en kan dus geen betrouwbare vernietiging garanderen.
Antwoord
Jij vraag waarom deze talen “niet zijn bijgewerkt met een optionele garbage collector.
Het probleem met de optionele garbage collection is dat je geen code kunt mixen die de verschillende modellen gebruikt. Dat wil zeggen, als ik code schrijf die ervan uitgaat dat je een garbage collector gebruikt, kun je deze niet gebruiken in je programma waarin garbage collection is uitgeschakeld. Als je dat doet, zal het overal lekken.
Antwoord
Er zijn verschillende problemen, waaronder …
- Hoewel GC werd uitgevonden vóór C ++, en mogelijk vóór C, werden zowel C als C ++ geïmplementeerd voordat GCs algemeen als praktisch werden aanvaard.
- U kunt niet gemakkelijk een GC-taal en platform zonder een onderliggende niet-GC-taal.
- Hoewel GC aantoonbaar efficiënter is dan niet-GC voor typische applicatiecode die is ontwikkeld in typische tijdschalen, enz., Zijn er problemen waarbij meer ontwikkelingsinspanningen een goede ruil zijn -off en gespecialiseerd geheugenbeheer zal beter presteren dan een algemene GC. Bovendien is C ++ doorgaans aantoonbaar efficiënter dan de meeste GC-talen, zelfs zonder enige extra ontwikkelingsinspanning.
- GC is niet universeel veiliger dan C ++ – stijl RAII . Met RAII kunnen andere bronnen dan geheugen automatisch worden opgeschoond, in feite omdat het betrouwbare en tijdige vernietigers ondersteunt. Deze kunnen niet worden gecombineerd met conventionele GC-methoden vanwege problemen met referentiecycli.
- GC-talen hebben hun eigen karakteristiek soorten geheugen lekken, met name met betrekking tot geheugen dat nooit meer zal worden gebruikt, maar waar bestaande referenties bestonden die nooit op nul zijn gezet of overschreven. De noodzaak om dit expliciet te doen is in principe niet anders dan de noodzaak om
delete
offree
expliciet te maken. De GC-benadering heeft nog steeds een voordeel – geen bungelende verwijzingen – en statische analyse kan sommige gevallen opvangen, maar nogmaals, er is niet één perfecte oplossing voor alle gevallen.
Kortom, gedeeltelijk wel ” s over de leeftijd van de talen, maar er zal sowieso altijd een plaats zijn voor niet-GC-talen – ook al is het een beetje een nichey-plek. En serieus, in C ++ is het ontbreken van GC geen probleem – je geheugen wordt anders beheerd, maar het wordt niet onbeheerd.
Door Microsoft beheerde C ++ heeft op zijn minst enig vermogen om GC en niet- GC in dezelfde applicatie, waardoor een mix-en-match van de voordelen van elk mogelijk is, maar ik heb niet de ervaring om te zeggen hoe goed dit in de praktijk werkt.
Rep-hoerige links naar gerelateerde antwoorden van mij …
- https://stackoverflow.com/questions/1529679/how-do-you-program-safely-outside-of-a-managed-code-environment/1529731#1529731
- https://stackoverflow.com/questions/1424660/garbage-collection-vs-non-garbage-collection-programming-languages/1496547#1496547
- https://stackoverflow.com/questions/4984849/why-circular-referenced-objects-with-del-defined-are-uncollectable-in-python/4984934#4984934
- https://stackoverflow.com/questions/5009869/how-to-implement-garbage-collection-in-c/5009984#5009984
Answer
Kun je je voorstellen dat je een apparaathandler schrijft in een taal met garbage collection? Hoeveel bits kunnen er in de regel terwijl de GC actief was?
Of een besturingssysteem? Hoe kon je de garbage collection starten voordat je de kernel startte?
C is ontworpen voor laag niveau dicht bij de hardwaretaken. Het probleem? is het zon leuke taal dat het ook een goede keuze is voor veel hogere taken. De taal-tsaren zijn op de hoogte van dit gebruik, maar ze moeten de vereisten van apparaatstuurprogrammas, embedded code en besturingssystemen als prioriteit ondersteunen.
Reacties
- C goed voor een hoog niveau? Ik snoof mijn drankje over mijn hele toetsenbord.
- Wel, hij zei " veel taken op een hoger niveau ". Hij zou kunnen trollen tellen (een, twee, veel …). En hij zei niet ' eigenlijk hoger dan wat. Maar grappen terzijde, het ' is waar – het bewijs is dat veel belangrijke projecten op een hoger niveau zijn met succes zijn ontwikkeld in C. Er zijn wellicht betere keuzes nu voor veel van die projecten, maar een werkproject is sterker bewijs dan speculatie over wat had kunnen zijn.
- Er zijn ' s enkele beheerde besturingssystemen, en ze werken redelijk goed. In feite, wanneer u het hele systeem beheert, daalt de prestatie van het gebruik van beheerde code zelfs nog lager, tot sneller dan onbeheerde code in real-life scenarios. Dat zijn natuurlijk allemaal " OS-onderzoek " – er zijn ' s vrijwel geen manier om ze compatibel te maken met bestaande onbeheerde code, naast het maken van een volledig gevirtualiseerd onbeheerd besturingssysteem binnen het beheerde besturingssysteem. Microsoft suggereerde op een gegeven moment dat ze Windows Server zouden vervangen door een van deze, aangezien er steeds meer servercode op .NET wordt geschreven.
Antwoord
Het korte en saaie antwoord op deze vraag is dat er een niet-garbagecollection-taal moet zijn voor de mensen die de garbage collectors schrijven. Het is conceptueel niet eenvoudig om een taal te hebben die tegelijkertijd een zeer nauwkeurige controle over de geheugenlay-out mogelijk maakt en een GC bovenaan draait.
De andere vraag is waarom C en C ++ geen garbage collectors hebben.Nou, ik weet dat C ++ er een paar heeft, maar ze zijn niet echt populair omdat ze worden gedwongen om te gaan met een taal die niet is ontworpen om te worden GC-ed, en de mensen die nog steeds C ++ gebruiken in dit tijdperk is niet echt het soort dat een GC mist.
In plaats van GC toe te voegen aan een oude niet-GC-ed taal, is het ook gemakkelijker om een nieuwe taal te creëren die de meeste van de dezelfde syntaxis terwijl een GC wordt ondersteund. Java en C # zijn hier goede voorbeelden van.
Reacties
- Ergens op programmers.se of SO, daar ' sa beweerde dat iemand tegen me zei dat iemand bezig was met een self-bootstrapping garbage-collectief ding – IIRC implementeerde in feite de VM met een GC-taal, met een bootstrapping-subset die werd gebruikt om de GC zelf te implementeren . Ik ben de naam vergeten. Toen ik ernaar keek, bleek dat ze ' d in feite nooit de sprong hadden gemaakt van de subset-zonder-GC naar het werkende GC-niveau. is mogelijk in principe, maar AFAIK het is in de praktijk nooit bereikt – het ' is zeker een kwestie van dingen op de moeilijke manier doen.
- @ Steve314: I ' zou dat graag zien als je je ooit herinnert waar je het gevonden hebt!
- vond het! Zie de opmerkingen bij stackoverflow.com/questions/3317329/… verwijzend naar de Klein VM. Deel van het probleem om het te vinden – de vraag was gesloten.
- Tussen haakjes – ik kan mijn opmerkingen niet beginnen met @missingno – wat geeft?
- @ steve314: Ik heb het antwoord op dit thread is bijgevoegd, ontvang ik al een melding voor alle reacties. Het plaatsen van een @ -post in dit geval zou overbodig zijn en is niet toegestaan door SE (don ' vraag me echter waarom ). (De echte oorzaak is echter dat mijn nummer ontbreekt)
Antwoord
Garbage collection is fundamenteel onverenigbaar met een systeemtaal die wordt gebruikt voor het ontwikkelen van stuurprogrammas voor hardware die DMA ondersteunt.
Het is heel goed mogelijk dat de enige wijzer naar een object wordt opgeslagen in een hardwareregister in een of ander randapparaat. Omdat de garbage collector het niet zou weten hierover zou het denken dat het object onbereikbaar was en het verzamelen.
Dit argument geldt dubbel voor het verdichten van GC. Zelfs als je voorzichtig zou zijn met het bijhouden van verwijzingen in het geheugen naar objecten die worden gebruikt door hardware-randapparatuur, zou de GC het object niet weten wanneer hij het object verplaatste, hij zou niet weten hoe de aanwijzer in het configuratieregister van randapparatuur moet worden bijgewerkt.
Dus nu “had je een combinatie van immobiele DMA-buffers en GC-beheerde objecten nodig, wat betekent dat je alle nadelen van beide hebt.
Reacties
- Ongetwijfeld alle nadelen van beide, maar minder gevallen van elk nadeel, en hetzelfde voor voordelen. Het is duidelijk dat er complexiteit zit in het hebben van meer soorten geheugenbeheer om mee om te gaan, maar er kan ook complexiteit worden vermeden door het juiste paard te kiezen voor elke cursus binnen uw code. Onwaarschijnlijk, denk ik, maar er is ' een theoretische kloof. Ik ' heb gespeculeerd over het mixen van GC en niet-GC in dezelfde taal, maar niet voor apparaatstuurprogrammas – meer voor het hebben van een voornamelijk GC-applicatie, maar met wat handmatig geheugenbeheerd laag niveau datastructuurbibliotheken.
- @ Steve314: Zou je niet ' zeggen dat onthouden welke objecten handmatig moeten worden vrijgemaakt net zo zwaar is als onthouden om alles vrij te maken? (Slimme verwijzingen kunnen natuurlijk bij beide helpen, dus geen van beide is een enorm probleem) En je hebt verschillende pools nodig voor handmatig beheerde objecten versus verzamelde / compacteerbare objecten, aangezien verdichting niet ' t werken goed als er overal vaste objecten zijn. Dus veel extra complexiteit voor niets.
- Niet als er ' een duidelijke scheidslijn is tussen de high-level code die allemaal GC is, en de low-level code code die zich afmeldt voor GC. Ik heb het idee voornamelijk ontwikkeld toen ik enkele jaren geleden naar D keek, waardoor je je kunt afmelden voor GC, maar je ' je niet opnieuw kunt aanmelden. Neem bijvoorbeeld een B + boombibliotheek . De container als geheel zou GC moeten zijn, maar de datastructuurknooppunten waarschijnlijk niet – het ' is efficiënter om een aangepaste scan door alleen de leaf-knooppunten uit te voeren dan om de GC een recursief zoeken door de vertakkingsknooppunten. Die scan moet de ingesloten items echter aan de GC rapporteren.
- Het punt is, dat ' een ingesloten stuk functionaliteit is. De B + -boomknooppunten behandelen als speciaal WRT-geheugenbeheer is niet anders dan ze behandelen als speciale WRT zijnde B + -boomknooppunten. Het ' is een ingekapselde bibliotheek, en de applicatiecode hoeft niet ' te weten dat GC-gedrag is omzeild / een speciale casus heeft.Behalve dat, althans op dat moment, dat onmogelijk was in D – zoals ik al zei, geen manier om je weer aan te melden en de ingesloten items aan de GC te rapporteren als mogelijke GC-roots.
Answer
Omdat C & C ++ relatief lage talen zijn die bedoeld zijn voor algemene doeleinden, zelfs voor bijvoorbeeld om te draaien op een 16-bits processor met 1 MB geheugen in een ingebed systeem, dat “geen geheugenverspilling kan veroorloven met gc.
Opmerkingen
- " Geïntegreerd systeem "? Toen C werd gestandaardiseerd (1989), moest het pcs met 1 MB geheugen.
- Ik ben het ermee eens, ik haalde een actueler voorbeeld aan.
- 1 MB ??? Holy schmoley, wie zou ooit zoveel RAM nodig hebben? < / billGates >
Antwoord
Er zijn garbage collectors in C ++ en C. Ik weet niet zeker hoe dit werkt in C, maar in C ++ kun je RTTI gebruiken om dynamisch je objectgrafiek te ontdekken en die te gebruiken voor garbage collection.
Voor zover ik weet, kun je geen Java schrijven zonder vuilnisman. Een kleine zoekopdracht leverde this op.
Het belangrijkste verschil tussen Java en C / C ++ is dat in C / C ++ de keuze altijd aan jou is , terwijl je in Java “door het ontwerp vaak zonder opties zit.
Opmerkingen
- En ook dat de toegewijde garbage collectors beter geïmplementeerd zijn, efficiënter en passen beter in de taal. 🙂
- Nee, je kunt ' geen RTTI gebruiken om de objectgrafiek dynamisch te ontdekken in C / C ++: It ' s de gewone oude data-objecten die alles bederven. Er is simpelweg geen RTTI-informatie opgeslagen in een gewoon oud data-object waarmee een garbage collector onderscheid kan maken tussen pointers en non-pointers binnen dat object. Erger nog, pointers hoeven niet perfect uitgelijnd te zijn op alle hardware, dus gegeven een 16 byte object, zijn er 9 mogelijke locaties waar een 64 bit pointer kan worden opgeslagen, waarvan er slechts twee niet ' t overlappen.
Answer
Het is een afweging tussen prestatie en veiligheid.
Er is geen garantie dat uw afval in Java wordt opgehaald, dus het kan lang rondhangen en ruimte in beslag nemen, terwijl het scannen naar objecten zonder verwijzing (dwz afval) ook langer duurt dan het expliciet verwijderen of vrijmaken van een ongebruikt object.
Het voordeel is natuurlijk dat men kan een taal bouwen zonder verwijzingen of zonder geheugenlekken, dus het is waarschijnlijker dat men de juiste code produceert.
Er kan soms een licht “religieus” randje aan deze debatten zijn – wees gewaarschuwd!
Antwoord
Hier is een lijst met inherente problemen van GC, die het onbruikbaar maken in een systeemtaal zoals C:
-
De GC moet draaien onder het niveau van de code waarvan de objecten worden beheerd. Een kernel heeft gewoonweg niet zon niveau.
-
Een GC moet de beheerde code van tijd tot tijd stoppen. Bedenk nu wat er zou gebeuren als het dat met je kernel zou doen. Alle verwerking op uw machine stopt voor bijvoorbeeld een milliseconde, terwijl de GC alle bestaande geheugentoewijzingen scant. Dit zou alle pogingen om systemen te creëren die onder strikte real-time vereisten werken, doden.
-
Een GC moet onderscheid kunnen maken tussen pointers en non-pointers. Dat wil zeggen, het moet in staat zijn om naar elk bestaand geheugenobject te kijken, en in staat zijn om een lijst met offsets te produceren waar de verwijzingen ervan kunnen worden gevonden.
Deze ontdekking moet perfect zijn: de GC moet in staat zijn om alle aanwijzingen die het ontdekt na te jagen. Als het een vals positief zou verwijderen, zou het waarschijnlijk crashen. Als het geen vals negatief zou ontdekken, zou het waarschijnlijk een object vernietigen dat nog in gebruik is, de beheerde code laten crashen of de gegevens stilletjes corrumperen.
Dit vereist absoluut dat typegegevens worden opgeslagen in elke afzonderlijke object bestaat. Zowel C als C ++ staan echter eenvoudige oude gegevensobjecten toe die geen type-informatie bevatten.
-
GC is een inherent traag bedrijf. Programmeurs die gesocialiseerd zijn met Java beseft dit misschien niet, maar programmas kunnen ordes van grootte sneller zijn als ze niet in Java zijn geïmplementeerd. En een van de factoren die Java traag maken, is GC. Dit is wat voorkomt dat GCed-talen zoals Java worden gebruikt in supercomputers. Als uw machine kost een miljoen per jaar aan stroomverbruik, je wilt zelfs geen 10% daarvan betalen voor afvalinzameling.
C en C ++ zijn talen die zijn gemaakt om alle mogelijke use-cases. En, zoals u ziet, worden veel van deze use-cases uitgesloten door garbage collection. Om deze gebruikssituaties te ondersteunen, kan C / C ++ dus niet als afval worden verzameld.