Kommentarer
- Vi ' har fått en modul i iPhone-utvikling dette semesteret. Etter å ha kodet apper for Android i to år, slo dette spørsmålet de fleste av klassen ganske hardt. Først nå ser vi hvor mange timer Java faktisk har reddet oss i å ikke måtte spore stygge minnestyringsfeil og ikke å måtte skrive kjeleplatekode.
- @NullUserException, siden det ikke ' t spesifiser en måte å gjenvinne minne som stort sett innebærer en GC.
- @ bizso09: Så du på ARC ennå? Du trenger ikke sakte / fett / ikke-deterministisk GC når du ' har fått systemstøtte for referansetelling: developer.apple. com / teknologier / ios5
- Svarene på dette ganske gode spørsmålet er fulle av religiøst tull.
- I C og C ++ er det mulig å ta en peker, kaste den til int og legg til et nummer i det. Senere trekker du tallet fra int og kaster resultatet tilbake til en peker. Du får den samme pekeren som før. Lykke til med å implementere en GC som IKKE samler det minnet mens adressen bare er lagret i variabelen som også har en annen verdi. Jeg vet at eksemplet er dumt, men en XOR-koblet liste bruker noe lignende. Jeg vil legge ut dette som et svar, men spørsmålet er lukket.
Svar
Søppelinnsamling krever datastrukturer for sporing av tildelinger og / eller referansetelling. Disse skaper overhead i minne, ytelse og språkets kompleksitet. C ++ er designet for å være «nær metallet», med andre ord, det tar den høyere ytelsessiden av kompromiss mot bekvemmelighetsfunksjoner. Andre språk gjør den kompromisset annerledes. Dette er en av hensynene til å velge språk, hvilken vekt du foretrekker.
Når det er sagt, er det mange ordninger for referansetelling i C ++ som er ganske lette og performante, men de er i biblioteker, både kommersielle og åpen kildekode, snarere enn en del av språket selv. Referansetelling for å håndtere objektets levetid er ikke det samme som søppelinnsamling, men det adresserer mange av de samme problemstillingene, og passer bedre med C ++ s grunnleggende tilnærming.
Kommentarer
- Et sekundært problem er at GC ikke er deterministisk. Objektet kan eller ikke fremdeles være i minnet lenge etter at programmet har " falt " det. Refcount-livssykluser er deterministiske, når den siste referansen slippes, blir minnet droppet. Dette har ikke bare implikasjoner for minneeffektivitet, men også for feilsøking. " zombie " objektet, referanseminne som teoretisk har blitt sluppet. GC er mye mer sannsynlig å maskere denne effekten, og produsere feil som er intermitterende og ekstremt vanskelige å spore.
- – moderne gc ' er verken sporfordeling eller teller referanser. De bygger en graf fra kvelden alt som er på bunken og bare kondenserer og tørker alt annet (forenklet), og GC resulterer normalt i redusert språkkompleksitet. Selv ytelsesfordelen er tvilsom.
- Er, @kylben, hele poenget med å ha automatisk GC bakt inn i språket er at det blir umulig å referere til zombieobjekter, fordi GC frigjør bare gjenstander som det er umulig å referere til! Du får den slags vanskelige sporbare feil du ' snakker om når du gjør feil med manuell minnestyring.
- -1, GC teller ikke referanser. I tillegg, avhengig av minneforbruket og tildelingsskjemaet ditt, kan en GC være raskere (med overhead i minnebruk). Så argumentet om ytelse er også feilslutning. Bare det nærme metallet er et gyldig punkt faktisk.
- Verken Java eller C # bruker referansetelling: GC-skjemaer basert på referansetelling er ganske primitive i sammenligning og fungerer mye dårligere enn moderne søppeloppsamlere (hovedsakelig fordi trenger å gjøre minneskrivninger for å endre referansetall når du kopierer en referanse!)
Svar
Strengt tatt, det er ingen minnestyring i det hele tatt på C-språket. malloc () og free () er ikke nøkkelord på språket, men bare funksjoner som kalles fra et bibliotek.Dette skillet kan være pedantisk nå, fordi malloc () og gratis () er en del av C-standardbiblioteket, og vil bli levert av enhver standardkompatibel implementering av C, men dette var ikke alltid sant tidligere.
Hvorfor vil du ha et språk uten standard for minnestyring? Dette går tilbake til Cs opprinnelse som «bærbar montering». Det er mange tilfeller av maskinvare og algoritmer som kan dra nytte av, eller til og med kreve, spesialiserte minnestyringsteknikker. Så vidt jeg vet er det ingen måte å deaktivere Javas native memory management og erstatte det med ditt eget. Dette er rett og slett ikke akseptabelt i noen høyytelses / minimale ressurssituasjoner. C gir nesten full fleksibilitet til å velge nøyaktig hvilken infrastruktur programmet ditt skal bruke. Prisen som betales er at C-språket gir svært liten hjelp til å skrive riktig, feilfri kode.
Kommentarer
- +1 for det generelle gode svaret, men også spesielt for " Prisen som betales er at C-språket gir veldig liten hjelp til å skrive riktig, feilfri kode "
- C har minneadministrasjon – men det fungerer bare, så folk merker det knapt. Det ' s statiske minne, registre og stack. Inntil du begynner å tildele ut av bunken, er du ' fin og dandy. Det ' er haugetildelingen som ødelegger ting . Som for Java kan alle skrive sin egen Java-kjøretid – det er ' mye å velge mellom, inkludert det som kan kalles " System ' s Java ". .NET kan gjøre stort sett alt C kan – det henger bare etter C ++ ' s native evner (f.eks. Klasser administreres bare i .NET). Selvfølgelig har du også C ++. NET, som har alt C ++ gjør, og alt. NET gjør.
- @Luaan I ' d sier at ' en veldig sjenerøs definisjon av å ha " minnestyring " " Inntil du begynner å tildele ut av dyngen, er du ' fin og dandy. Det ' er haugetildelingen som ødelegger ting ", at ' er som å si en bil er et perfekt bra fly, den er bare ikke ' t i stand til å fly.
- @ CharlesE.Grant Vel, et rent funksjonelt språk kan gjøre alt med det slags minnehåndtering. Bare fordi haugetildeling er en god avveiing i noen brukstilfeller, betyr ikke ' t at det ' er referanseindeksen for alle språk / kjøretider . Det ' er ikke som minneadministrasjon slutter å være " minnestyring " bare fordi det ' s enkle, rett frem, skjult bak kulissene. Å designe statisk minnetildeling er fremdeles minnehåndtering, det samme er en god bruk av stabelen og alt annet du har tilgjengelig.
- " enhver standardkompatibel implementering " er ikke sant, bare for standardkompatibel vertsmiljøimplementering. Noen plattformer / standardbiblioteker, mest for 8 eller 16-bits innebygd mikrokontroller, gir ikke
malloc()
ellerfree()
. (eksempel er MLAP-kompilatorer for PIC)
Svar
Det virkelige svaret er at den eneste måten å lage en sikker, effektiv søppeloppsamlingsmekanisme er å ha språkstøtte for ugjennomsiktige referanser. (Eller omvendt, en mangel på språknivå for direkte minnebehandling.)
Java og C # kan gjøre det fordi de har spesielle referansetyper som ikke kan manipuleres. Dette gir kjøretiden frihet til å gjøre ting som flytte tildelte objekter i minnet , noe som er avgjørende for en GC-implementering med høy ytelse .
For ordens skyld bruker ingen moderne GC-implementering referansetelling , så det er helt rødt sild. Moderne GC-er bruker generasjonssamling, der nye tildelinger blir behandlet i hovedsak på samme måte som stakkallokeringer er på et språk som C ++, og deretter flyttes alle nylig tildelte objekter som fortsatt er i live til et eget «overlevende» rom og en hel generasjon av objekter blir fordelt på en gang.
Denne tilnærmingen har fordeler og ulemper: oppsiden er at haugetildelinger på et språk som støtter GC, er like raskt som stakkallokeringer på et språk som ikke støtter GC, og ulempen er at objekter som må utføre opprydding før de blir ødelagt, enten krever en separat mekanisme (f.eks. C #» s using
søkeord) ellers kjøres oppryddingskoden ikke-deterministisk.
Merk at en nøkkel til en høyytelses GC er at det må være språkstøtte for en spesiell klasse referanser. C har ikke denne språkstøtten og vil aldri; fordi C ++ har overbelastning av operatøren, kan den etterligne en GC-pekertype, selv om det må gjøres nøye. Når Microsoft oppfant dialekten deres av C ++ som skulle kjøre under CLR (.NET runtime), måtte de faktisk oppfinne en ny syntaks for «C # -stil referanser» (f.eks. Foo^
) for å skille dem fra «C ++ – stilreferanser» (f.eks. Foo&
).
Hva C ++ har, og det som regelmessig brukes av C ++ programmerere, er smarte pekere , som egentlig bare er en referansetellingmekanisme. Jeg vil ikke anse referansetelling for å være «sann» GC, men det gir mange av de samme fordelene, på bekostning av langsommere ytelse enn enten manuell minnestyring eller ekte GC, men med fordelen av deterministisk ødeleggelse.
På slutten av dagen koker svaret virkelig til en språkdesignfunksjon. C tok ett valg, C ++ tok et valg som gjorde det mulig å være bakoverkompatibel med C, mens de fremdeles ga alternativer som er gode nok til de fleste formål, og Java og C # tok et annet valg som er uforenlig med C, men som også er bra nok til de fleste formål. Dessverre er det ingen sølvkule, men å være kjent med de forskjellige valgene der ute, vil hjelpe deg å velge den riktige uansett hvilket program du for øyeblikket prøver å bygge.
Kommentarer
- Dette er det faktiske svaret på spørsmålet
- For c ++ delen, i dag bør du se på std :: unik_ptr og std :: flytte 🙂
- ingen moderne GC implem entasjon bruker referansetelling : cPython bruker både referansetelling og automatisk samling .
- @ Mike76: På tildelingssiden vil en GC-tildeler jobbe omtrent like raskt som stakkallokering, og GC kan distribuere tusenvis av objekter samtidig. Uansett hva du gjør med en ref-telling implementering, vil tildeling og deallocation aldri være raskere enn
malloc
ogfree
. Så ja, en GC kan være vesentlig raskere. (Merk at jeg sa " kan være " – selvfølgelig påvirkes den eksakte ytelsen til hvert program av mange faktorer.) - ingen moderne GC-implementering bruker referansetelling Swift bruker automatisk referansetelling.
Svar
Fordi når du bruker kraften til C ++, er det ikke noe behov.
Herb Sutter:» Jeg har ikke skrevet å slette i år. »
se Skrive moderne C ++ – kode: hvordan C ++ har utviklet seg gjennom årene 21:10
Det kan overraske mange erfarne C ++ programmerere.
Kommentarer
- Interessant. Lesestoffet mitt for i dag.
- Bah, en video. Men likevel, interessant allerede.
- interessant video. 21 minutter inn og 55 minutter var de beste bitene. Synd at WinRT-samtalene fremdeles så ut til å være C ++ / CLI bumpf.
- @ dan04: Det er '. Men hvis du skriver i C, får du det du ber om.
- Det er ikke mer krevende å administrere smarte pekere enn å sørge for at du ikke ' t ha unødvendige referanser i et søppel samlet miljø. Fordi GC ikke kan ' t lese tankene dine, er det ' heller ikke magisk.
Svar
«Alt» en søppelsamler er, er en prosess som kjører med jevne mellomrom for å se om det er noen ikke-refererte objekter i minnet, og om det er slettet. (Ja, jeg vet at dette er en grov forenkling). Dette er ikke en egenskap for språket, men rammeverket.
Det er søppeloppsamlere skrevet for C og C ++ – denne for eksempel .
En grunn til at man ikke har blitt «lagt» til språket, kan være på grunn av det store volumet av eksisterende kode som aldri vil bruke den da de bruker sin egen kode for å administrere minne. En annen grunn kan være være at typene applikasjoner skrevet i C og C ++ ikke trenger overhead forbundet med en søppeloppsamlingsprosess.
Kommentarer
- Men fremtidige programmer skrevet ville begynne å bruke søppeloppsamleren, ikke sant?
- Selv om søppeloppsamling er teoretisk uavhengig av ethvert programmeringsspråk, er det ganske vanskelig å skrive en nyttig GC for C / C ++, og til og med umulig å lage en idiotsikker (minst like idiotsikker som Java ' s) – årsaken til at Java kan trekke den, er fordi den kjører i et kontrollert virtualisert miljø. Omvendt er Java-språket designet for GC, og du ' har vanskelig for å skrive en Java-kompilator som ikke ' ikke gjør GC .
- @tdammers: Jeg er enig i at søppeloppsamling må støttes av språket for å være mulig. Hovedpoenget er imidlertid ikke virtualisering og kontrollert miljø, men streng skriving. C og C ++ er svakt skrevet, så de tillater ting som å lagre pekeren i heltallvariabler, rekonstruere pekere fra forskyvninger og slike ting som forhindrer samleren fra å kunne fortelle pålitelig hva som er tilgjengelig (C ++ 11 forbyr det senere å tillate konservative samlere). I Java vet du alltid hva som er en referanse, slik at du kan samle den presist, selv om du er kompilert til native.
- @Thorbj ø rnRavnAndersen: Jeg kan skrive en gyldig C-program som lagrer pekere på en slik måte at ingen søppeloppsamler noen gang kunne finne dem. Hvis du så hekter en søppeloppsamler på
malloc
ogfree
, ville du ødelegge det riktige programmet mitt. - @Thorbj ø rnRavnAndersen: Nei, jeg ville ikke ' t ring
free
til jeg var ferdig med det . Men den foreslåtte søppeloppsamleren din som ikke ' ikke frigjør minnet til jeg eksplisitt kallerfree
isn ' ta søppeloppsamler i det hele tatt.
Svar
C ble designet i en tid da søppeloppsamlingen knapt var et alternativ. Det var også ment for bruk der søppeloppsamling vanligvis ikke ville fungere – bart metall, sanntidsmiljøer med minimalt minne og minimal driftstidsbruk. Husk at C var implementeringsspråket for den første unixen, som kjørte på en pdp-11 med 64 * K * minne. C ++ var opprinnelig en utvidelse av C – valget var allerede gjort, og det er veldig vanskelig å pode søppeloppsamling på et eksisterende språk. Det er den typen ting som må bygges inn fra første etasje. p>
Svar
Jeg har ikke de eksakte sitatene, men både Bjarne og Herb Sutter sier noe i retning av:
C ++ trenger ikke en søppeloppsamler, fordi den ikke har noe søppel.
I moderne tid C ++ bruker du smarte pekere og har derfor ikke noe søppel.
Kommentarer
- hva er smarte pekere?
- hvis det var det enkelt, ingen ville ha implementert noen GC.
- @deadalnix: Ikke sant, fordi ingen noen gang implementerer noe altfor komplisert, sakte, oppblåst eller unødvendig. All programvare er 100% effektiv hele tiden, ikke sant?
- @deadalnix – C ++ -tilnærmingen til minneadministrasjon er nyere enn søppeloppsamlere. RAII ble oppfunnet av Bjarne Stroustrup for C ++. Destruktøropprydding er en eldre idé, men reglene for å sikre unntakssikkerhet er nøkkelen. Jeg vet ikke ' når nøyaktig når selve ideen ble beskrevet, men den første C ++ – standarden ble avsluttet i 1998, og Stroustrups " Design og evolusjon av C ++ " var ikke ' t publisert til 1994, og unntak var et relativt nylig tillegg til C ++ – etter publisering av " Annotated C ++ Reference Manual " i 1990, tror jeg. GC ble oppfunnet i 1959 for Lisp.
- @deadalnix – er du klar over at minst en Java VM brukte en referansetelling GC som (nesten) kunne implementeres ved bruk av C ++ – stil RAII ved hjelp av en smart pekerklasse – nettopp fordi det var mer effektivt for flertrådet kode enn eksisterende virtuelle maskiner? Se www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf. En grunn til at du ikke ' ikke ser dette i C ++ i praksis, er den vanlige GC-samlingen – den kan samle sykluser, men kan ' ikke velge en sikker destruktørrekkefølge i nærvær av sykluser, og kan dermed ikke sikre pålitelig destruktøropprydding.
Svar
Du spør hvorfor disse språkene ikke har blitt oppdatert slik at de inkluderer en valgfri søppeloppsamler.
Problemet med valgfri søppelinnsamling er at du ikke kan blande kode som bruker de forskjellige modellene. Det vil si at hvis jeg skriver kode som antar at du bruker en søppeloppsamler, kan du ikke bruke den i programmet som har søppeloppsamling slått av. Hvis du gjør det, vil den lekke overalt.
Svar
Det er forskjellige problemer, inkludert …
- Selv om GC ble oppfunnet før C ++, og muligens før C, ble både C og C ++ implementert før GC ble allment akseptert som praktisk.
- Du kan ikke enkelt implementere en GC-språk og plattform uten et underliggende ikke-GC-språk.
- Selv om GC er beviselig mer effektiv enn ikke-GC for typiske applikasjonskoder utviklet i typiske tidsskalaer osv., Er det problemer der mer utviklingsarbeid er en god handel -av og spesialisert minneadministrasjon vil overgå en generell GC. Dessuten er C ++ beviselig mer effektiv enn de fleste GC-språk, selv uten ekstra utviklingsinnsats.
- GC er ikke universelt tryggere enn C ++ – stil RAII RAII gjør det mulig å rydde opp i andre ressurser enn minne automatisk, i utgangspunktet fordi den støtter pålitelige og betimelige destruktører. Disse kan ikke kombineres med konvensjonelle GC-metoder på grunn av problemer med referansesykluser. slags hukommelse lekkasjer, spesielt knyttet til minne som aldri vil bli brukt igjen, men hvor eksisterende referanser eksisterte som aldri har blitt opphevet eller overskrevet. Behovet for å gjøre dette eksplisitt er ikke annerledes i prinsippet enn behovet for å
delete
ellerfree
eksplisitt. GC-tilnærmingen har fremdeles en fordel – ingen dinglende referanser – og statisk analyse kan fange noen tilfeller, men igjen, det er ingen perfekt løsning for alle tilfeller.
I utgangspunktet, delvis det » handler om språkens alder, men det vil alltid være et sted for ikke-GC-språk uansett – selv om det er litt nichey sted. Og seriøst, i C ++, er mangelen på GC ikke så stor sak – minnet ditt styres annerledes, men det er ikke ustyrt.
Microsofts managed C ++ har i det minste noen evne til å blande GC og ikke- GC i samme applikasjon, slik at du kan kombinere fordelene fra hver, men jeg har ikke erfaring med å si hvor godt dette fungerer i praksis.
Rep-whoring lenker til relaterte svar av meg …
- 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
Svar
Kan du forestille deg å skrive en enhetsbehandler på et språk med søppelsamling? Hvor mange biter kan komme nedover linje mens GC kjørte?
Eller et operativsystem? Hvordan kan du starte søppelinnsamlingen som kjører før du til og med starter kjernen?
C er designet for lavt nivå nær maskinvareoppgavene. Problemet? er det et så hyggelig språk at det er et godt valg for mange oppgaver på høyere nivå også. Språkzarene er klar over disse bruksområdene, men de trenger å støtte kravene til enhetsdrivere, innebygd kode og operativsystemer som en prioritet.
Kommentarer
- C bra for høyt nivå? Jeg fnysket drikken min over tastaturet.
- Vel, han sa " mange oppgaver på høyere nivå ". Han kunne telle troll (en, to, mange …). Og han sa ikke ' t høyere enn hva. Vitser til side, skjønt, er det ' sant – beviset er at mange viktige prosjekter på høyere nivå er vellykket utviklet i C. Det kan være bedre valg nå for mange av disse prosjektene, men et arbeidsprosjekt er sterkere bevis enn spekulasjoner om hva som kan ha vært.
- ' er noen administrerte operativsystemer, og de fungerer ganske bra. Når du gjør hele systemet administrert, synker ytelsen fra å bruke administrert kode enda lavere, opp til å være raskere enn ukontrollert kode i virkelige scenarier. Selvfølgelig er det alle " research OS " – det ' er ganske mye nei måte å gjøre dem kompatible med eksisterende, ikke-administrert kode, i tillegg til å lage et fullstendig virtualisert, ikke-administrert operativsystem i det administrerte operativsystemet. Microsoft foreslo på et tidspunkt at de kanskje erstattet Windows Server med en av disse, ettersom flere og flere serverkoder skrives på. NET.
Svar
Det korte og kjedelige svaret på dette spørsmålet er at det må være et språk som ikke er søppeloppsamlet der ute for de som skriver søppeloppsamlerne. Det er ikke begrepsmessig enkelt å ha et språk som samtidig gir veldig nøyaktig kontroll over minneoppsettet og har en GC som kjører på toppen.
Det andre spørsmålet er hvorfor C og C ++ ikke har søppeloppsamlere.Vel, jeg vet at C ++ har et par av dem rundt, men de er ikke veldig populære fordi de er tvunget til å håndtere et språk som ikke var designet for å bli GC-ed i utgangspunktet, og menneskene som fremdeles bruker C ++ i denne alderen er egentlig ikke den typen som savner en GC.
I stedet for å legge til GC til et gammelt språk som ikke er GC-ed, er det faktisk lettere å lage et nytt språk som har det meste av samme syntaks mens du støtter en GC. Java og C # er gode eksempler på dette.
Kommentarer
- Et eller annet sted på programmers.se eller SO, der ' en påstand om at noen sa til meg at noen jobbet med en selvoppstartende søppel-samlet ting – IIRC implementerte i utgangspunktet VM ved hjelp av et GC-språk, med et bootstrapping-delmengde som ble brukt til å implementere selve GC . Jeg glemmer navnet. Da jeg så på det, viste det seg at de ' i utgangspunktet aldri nådde spranget fra delsett-uten-GC til arbeids-GC-nivået. Dette er mulig i prinsippet, men AFAIK har det aldri blitt oppnådd i praksis – det ' er absolutt et tilfelle av å gjøre ting på den harde måten.
- @ Steve314: Jeg ' Jeg elsker å se det hvis du noen gang husker hvor du fant det!
- fant det! Se kommentarene til stackoverflow.com/questions/3317329/… med henvisning til Klein VM. En del av problemet med å finne det – spørsmålet ble lukket.
- BTW – Jeg ser ut til å ikke kunne starte kommentarene mine med @missingno – hva gir?
- @ steve314: Har jeg fått svaret dette tråd er knyttet til, mottar jeg allerede et varsel for alle kommentarer. Å gjøre en @ -post i dette tilfellet vil være overflødig og er ikke tillatt av SE (ikke ' t spør meg hvorfor skjønt). (Den virkelige årsaken er imidlertid fordi nummeret mitt mangler)
Svar
Søppeloppsamling er i utgangspunktet uforenlig med en systemspråk som brukes til å utvikle drivere for DMA-kompatibel maskinvare.
Det er fullt mulig at den eneste pekeren til et objekt vil bli lagret i et maskinvareregister i noen periferi. Siden søppeloppsamleren ikke vet om dette, vil det tro at objektet ikke kan nås og samle det.
Dette argumentet holder dobbelt for å komprimere GC. Selv om du var forsiktig med å opprettholde referanser i minnet til objekter som brukes av maskinvareutstyr, da GC flyttet objektet, ville den ikke vite hvordan du oppdaterer pekeren i det perifere konfigurasjonsregisteret.
Så nå trenger du en blanding av immobile DMA-buffere og GC-administrerte objekter, noe som betyr at du har alle ulempene med begge deler.
Kommentarer
- Uten tvil alle ulempene med begge, men færre forekomster av hver ulempe, og det samme for fordeler. Det er tydelig at det er kompleksitet i å ha flere typer minnehåndtering å håndtere, men det kan også være kompleksitet unngås ved å velge riktig hest for hvert kurs i koden din. Usannsynlig forestiller jeg meg, men det er ' et teoretisk gap der. Jeg ' har spekulert i å blande GC og ikke-GC på samme språk før, men ikke for enhetsdrivere – mer for å ha et stort sett GC-program, men med noe manuelt minnestyrt lavt nivå datastrukturbiblioteker.
- @ Steve314: Ville ikke ' t å si at det å huske hvilke objekter som må frigjøres manuelt, er like belastende som å huske å frigjøre alt? (Selvfølgelig kan smarte pekere hjelpe med begge deler, så ingen av dem er et stort problem) Og du trenger forskjellige bassenger for manuelt administrerte objekter vs samlet / komprimerbare objekter, siden komprimering ikke ' t fungerer bra når det er faste gjenstander spredt overalt. Så mye ekstra kompleksitet for ingenting.
- Ikke hvis det ' er et klart skille mellom høynivåkoden som er GC, og lavnivået kode som velger ut av GC. Jeg utviklet hovedsakelig ideen mens jeg så på D for noen år siden, som lar deg velge bort GC, men ikke ' t tillater deg å melde deg på igjen. Ta for eksempel et B + trebibliotek . Beholderen som helhet skal være GC, men datastrukturen noder sannsynligvis ikke – det ' er mer effektivt å gjøre en tilpasset skanning gjennom bladnodene bare enn å få GC til å gjøre en rekursivt søk gjennom grennodene. Imidlertid trenger denne skanningen å rapportere de inneholdte elementene til GC.
- Poenget er at ' er en inneholdt funksjonalitet. Å behandle B + tre-nodene som spesiell WRT-minneadministrasjon er ikke annerledes enn å behandle dem som spesielle WRT å være B + tre-noder. Det ' er et innkapslet bibliotek, og applikasjonskoden trenger ikke ' å vite at GC-oppførsel er omgått / spesiell tilfelle.Bortsett fra at det, i det minste på det tidspunktet, var umulig i D – som sagt, ingen måte å melde seg på og rapportere de inneholdte elementene til GC som potensielle GC-røtter.
Svar
Fordi C & C ++ er relativt lave nivå språk ment for generelle formål, til og med for eksempel å kjøre på en 16-biters prosessor med 1 MB minne i et innebygd system, som ikke hadde råd til å kaste bort minne med gc.
Kommentarer
- " Innebygd system "? Da C ble standardisert (1989), trengte den å kunne håndtere PCer med 1 MB minne.
- Jeg er enig, jeg siterte et mer aktuelt eksempel.
- 1 MB ??? Holy schmoley, hvem ville noen gang trenge så mye RAM? < / billGates >
Svar
Det er søppeloppsamlere i C ++ og C. Ikke sikker på hvordan dette fungerer i C, men i C ++ kan du utnytte RTTI for dynamisk å oppdage objektgrafen din og bruke den til søppelinnsamling.
Så vidt jeg vet, kan du ikke skrive Java uten søppeloppsamler. Et lite søk viste dette .
Hovedforskjellen mellom Java og C / C ++ er at i C / C ++ er valget alltid ditt , mens du i Java ofte blir stående uten valg etter design.
Kommentarer
- Og også at de dedikerte søppeloppsamlerne er bedre implementert, mer effektive og passer bedre inn i språket. 🙂
- Nei, du kan ' t bruke RTTI til å dynamisk oppdage objektgrafen i C / C ++: Det ' er de vanlige gamle dataobjektene som ødelegger alt. Det er ganske enkelt ingen RTTI-informasjon lagret i et vanlig gammelt dataobjekt som gjør det mulig for en søppeloppsamler å skille mellom pekere og ikke-pekere i det objektet. Enda verre, pekere trenger ikke å være perfekt justert på all maskinvare, så gitt et 16 byte-objekt er det 9 mulige steder en 64-biters peker kan lagres, hvorav bare to ikke ' t overlapping.
Svar
Det er en avveining mellom ytelse og sikkerhet.
Det er ingen garanti for at søppelet ditt blir samlet inn på Java, så det kan hænge rundt og bruke opp plass i lang tid, mens skanningen etter objekter uten referanse (dvs. søppel) også tar lengre tid enn å eksplisitt slette eller frigjøre et ubrukt objekt.
Fordelen er selvfølgelig at man kan bygge et språk uten pekere eller uten minnelekkasjer, så det er mer sannsynlig at man produserer riktig kode.
Det kan være en liten «religiøs» kant til disse debattene noen ganger – vær advart!
Svar
Her er en liste over iboende problemer med GC, som gjør den ubrukelig i et systemspråk som C:
-
GC må kjøre under nivået på koden hvis objekter den administrerer. Det er rett og slett ikke noe slikt nivå i en kjerne.
-
En GC må stoppe den administrerte koden fra tid til annen. Tenk nå på hva som ville skje hvis det gjorde det med kjernen din. All behandling på maskinen din vil stoppe i for eksempel et millisekund, mens GC skanner alle eksisterende minnetildelinger. Dette vil drepe alle forsøk på å lage systemer som fungerer under strenge sanntidskrav.
-
En GC må kunne skille mellom pekere og ikke-pekere. Det vil si at den må kunne se på hvert minneobjekt som eksisterer, og kunne produsere en liste over forskyvninger der pekerne kan bli funnet.
Denne oppdagelsen må være perfekt: GC må kunne å jage alle pekepinnene den oppdager. Hvis det refererte til en falsk positiv, ville det sannsynligvis krasje. Hvis det ikke oppdaget en falsk negativ, ville det sannsynligvis ødelegge et objekt som fortsatt er i bruk, krasje den administrerte koden eller stille ødelegge dataene.
Dette krever absolutt at typeinformasjon lagres i hver eneste objekt eksisterer. Både C og C ++ tillater imidlertid vanlige gamle dataobjekter som ikke inneholder noen typeinformasjon.
-
GC er en iboende treg virksomhet. Programmører som har blitt sosialisert med Java kan ikke forstå dette, men programmer kan være størrelsesordener raskere når de ikke implementeres i Java. Og en av faktorene som gjør Java treg er GC. Dette er det som utelukker at GCed-språk som Java blir brukt i superdatamaskiner. Hvis maskinen din koster en million i år i strømforbruk, vil du ikke betale enda 10% av det for søppeloppsamling.
C og C ++ er språk som er laget for å støtte alle mulige brukssaker. Og som du ser, er mange av disse brukssakene utelukket av søppeloppsamling. Så, for å støtte disse brukssakene, kan ikke C / C ++ samles opp søppel.