Kommentarer
- Vi ' har fått en modul i iPhone-utveckling den här terminen. Efter att ha kodat appar för Android i två år slog denna fråga de flesta i klassen ganska hårt. Först nu ser vi hur många timmar Java faktiskt har räddat oss genom att inte behöva spåra otäcka minneshanteringsfel och inte behöva skriva pannkodskod.
- @NullUserException, eftersom det inte ' t ange ett sätt att återta minne som i stort sett innebär en GC.
- @ bizso09: Tittade du på ARC än? Inget behov av långsam / fett / icke-deterministisk GC när du ' har fått systemstöd för referensräkning: developer.apple. com / teknologier / ios5
- Svaren på denna ganska bra fråga är fulla av religiös skitsnack.
- I C och C ++ är det möjligt att ta en pekare, kasta den till int och lägg till ett nummer till det. Senare subtrahera numret från int och kasta resultatet tillbaka till en pekare. Du får samma pekare som tidigare. Lycka till med att implementera en GC som INTE samlar in minnet medan dess adress endast lagras i variabeln som också har ett annat värde. Jag vet att exemplet är dumt men en XOR-länkad lista använder något liknande. Jag skulle lägga upp detta som ett svar men frågan är stängd.
Svar
Insamling av skräp kräver datastrukturer för spårningstilldelningar och / eller referensräkning. Dessa skapar overhead i minne, prestanda och språkets komplexitet. C ++ är utformad för att vara ”nära metallen”, med andra ord tar den den högre prestandasidan av avvägningen jämfört med bekvämlighetsfunktionerna. Andra språk gör att avvägningen blir annorlunda. Detta är en av övervägandena när du väljer språk, vilken betoning du föredrar.
Som sagt, det finns många scheman för referensräkning i C ++ som är ganska lätta och performanta, men de finns i bibliotek, både kommersiella och öppen källkod, snarare än en del av själva språket. Referensräkning för att hantera objektets livslängd är inte detsamma som skräpsamling, men det tar upp många av samma slags problem och passar bättre med C ++: s grundläggande strategi.
Kommentarer
- Ett sekundärt problem är att GC är icke-deterministisk. Objektet kanske eller kanske inte finns i minnet långt efter att programmet har " tappat " det. Livscykler för återräkning är deterministiska, när den sista referensen tappas, tappas minnet. Detta har inte bara konsekvenser för minneseffektivitet utan också för felsökning. Ett vanligt programmeringsfel är " zombie " objekt, referensminne som teoretiskt har tappats. GC är mycket mer benägna att maskera denna effekt och producera buggar som är intermittenta och extremt svåra att spåra.
- – moderna gc ' är varken spårallokeringar eller räknar referenser. De bygger en graf från kvällen allting för närvarande på stacken och bara kondensera och torka allt annat (förenklat), och GC resulterar normalt i reducerad språkkomplexitet. Till och med prestationsfördelen är ifrågasatt.
- Er, @kylben, hela poängen med att ha automatisk GC bakad till språket är att det blir omöjligt att referera till zombieobjekt, eftersom GC frigör bara objekt som är omöjliga att referera till! Du får den typ av svåra att spåra buggar som du ' talar om när du gör misstag med manuell minneshantering.
- -1, GC räknas inte referenser. Plus, beroende på din minnesanvändning och tilldelningsschema, kan en GC vara snabbare (med en overhead i minnesanvändningen). Så argumentet om prestanda är också fel. Bara det nära metall är faktiskt en giltig punkt.
- Varken Java eller C # använder referensräkning: GC-scheman baserade på referensräkning är ganska primitiva i jämförelse och fungerar mycket sämre än moderna sopor (främst för att de måste göra minnesskrivningar för att ändra referensräkningarna när du kopierar en referens!)
Svar
Strikt taget, det finns ingen minneshantering alls på C-språket. malloc () och free () är inte nyckelord på språket, utan bara funktioner som anropas från ett bibliotek.Denna skillnad kan vara pedantisk nu, eftersom malloc () och gratis () är en del av C-standardbiblioteket och kommer att tillhandahållas av alla standardkompatibla implementeringar av C, men det var inte alltid sant tidigare.
Varför vill du ha ett språk utan standard för minneshantering? Detta går tillbaka till C: s ursprung som ”bärbar montering”. Det finns många fall av hårdvara och algoritmer som kan dra nytta av eller till och med kräva specialiserad minneshanteringsteknik. Såvitt jag vet finns det inget sätt att helt inaktivera Java: s inbyggda minneshantering och ersätta det med ditt eget. Detta är helt enkelt inte acceptabelt i vissa högpresterande / minimala resursituationer. C ger nästan fullständig flexibilitet för att välja exakt vilken infrastruktur. ditt program kommer att användas. Priset som betalas är att C-språket ger väldigt lite hjälp med att skriva korrekt, felfri kod.
Kommentarer
- +1 för det övergripande bra svaret, men också speciellt för " Priset som betalas är att C-språket ger väldigt lite hjälp med att skriva korrekt, felfri kod "
- C har minneshantering – men det fungerar bara, så folk märker det knappt. Det ' s statiska minne, register och stack. Tills du börjar allokera ut ur högen är du ' bra och dandy. Det ' är högtilldelningen som förstör saker . Som för Java kan alla skriva sin egen Java-runtime – det finns ' mycket att välja mellan, inklusive vad som kan kallas " System ' s Java ". .NET kan göra i stort sett allt som C kan – det ligger bara efter C ++ ' s inbyggda funktioner (t.ex. klasser hanteras endast i .NET). Naturligtvis har du också C ++. NET, som har allt som C ++ gör, och allt. NET gör.
- @Luaan I ' d säger att ' en mycket generös definition av att ha " minneshantering " " Tills du börjar allokera ur högen är du ' bra och dandy. Det ' är högtilldelningen som förstör saker ", att ' är som att säga en bil är ett perfekt bra flygplan, det är bara inte ' som inte kan flyga.
- @ CharlesE.Grant Tja, ett rent funktionellt språk kan göra allt med det typ av minneshantering. Bara för att högtilldelning är en bra avvägning i vissa användningsfall betyder inte ' att det ' är riktmärket för alla språk / körtider . Det ' är inte som minneshantering slutar vara " minneshantering " bara för att det ' är enkelt, rakt fram, gömt bakom kulisserna. Att utforma statisk minnestilldelning är fortfarande minneshantering, liksom en bra användning av stacken och allt annat du har tillgängligt.
- " alla standardkompatibla implementeringar " är inte sant, endast för standardkompatibel värdmiljöimplementering. Vissa plattformar / standardbibliotek, mest för 8 eller 16-bitars inbäddad mikrokontroller, tillhandahåller inte
malloc()
ellerfree()
. (exempel är MLAP-kompilatorer för PIC)
Svar
Det verkliga svaret är att det enda sättet att göra en säker och effektiv sopmekanism är att ha språkstöd för ogenomskinliga referenser. (Eller omvänt, brist på språknivå för direktminnesmanipulation.)
Java och C # kan göra det eftersom de har speciella referenstyper som inte kan manipuleras. Detta ger körtiden friheten att göra saker som flytta tilldelade objekt i minnet , vilket är avgörande för en högpresterande GC-implementering .
För ordens skull använder ingen modern GC-implementering referensräkning , så det är helt rött sill. Moderna GC använder generationssamling, där nya allokeringar behandlas väsentligen på samma sätt som stackallokeringar är på ett språk som C ++, och sedan flyttas periodiskt alla nyligen allokerade objekt som fortfarande lever till ett separat ”survivor” -utrymme och en hel generation föremål delas omedelbart.
Detta tillvägagångssätt har fördelar och nackdelar: uppåtriktningen är att högtilldelningar på ett språk som stöder GC är lika snabbt som stackallokeringar på ett språk som inte stöder GC, och nackdelen är att objekt som behöver rengöras innan de förstörs antingen kräver en separat mekanism (t.ex. C #” s using
nyckelord) eller så går deras saneringskod icke-deterministiskt.
Observera att en nyckel till en högpresterande GC är att det måste finnas språkstöd för en speciell referensklass. C har inte detta språkstöd och kommer aldrig att göra det; eftersom C ++ har överbelastning av operatören kan det emulera en GC-pekartyp, även om det måste göras noggrant. Faktum är att när Microsoft uppfann sin dialekt av C ++ som skulle köras under CLR (.NET runtime), var de tvungna att uppfinna en ny syntax för ”C # -stil referenser” (t.ex. Foo^
) för att skilja dem från ”C ++ – stilreferenser” (t.ex. Foo&
).
Vad C ++ har och vad som regelbundet används av C ++ – programmerare är smarta pekare , som egentligen bara är en referensräkningsmekanism. Jag skulle inte betrakta referensräkning som ”sann” GC, men det ger många av samma fördelar, till en kostnad av långsammare prestanda än antingen manuell minneshantering eller sann GC, men med fördelen av deterministisk förstörelse.
I slutet av dagen beror svaret verkligen på en språkdesignfunktion. C gjorde ett val, C ++ gjorde ett val som gjorde att det kunde vara bakåtkompatibelt med C samtidigt som det tillhandahöll alternativ som är tillräckligt bra för de flesta syften, och Java och C # gjorde ett annat val som är oförenligt med C men som också är tillräckligt bra för de flesta ändamål. Tyvärr finns det ingen silverkula, men att vara bekant med de olika alternativen där ute hjälper dig att välja rätt för vilket program du för närvarande försöker bygga.
Kommentarer
- Detta är det faktiska svaret på frågan
- För c ++ -delen, nuförtiden bör du titta på std :: unique_ptr och std :: move 🙂
- inget modernt GC-implem entation använder referensräkning : cPython använder både referensräkning och automatisk samling .
- @ Mike76: På allokeringssidan kommer en GC-fördelare att fungera ungefär lika snabbt som stackallokering, och GC kan omplacera tusentals objekt samtidigt. Oavsett vad du gör med en ref-räkningsimplementering kommer allokering och deallocation aldrig att vara snabbare än
malloc
ochfree
. Så ja, en GC kan vara väsentligt snabbare. (Observera att jag sa " kan vara " – naturligtvis påverkas varje programs exakta prestanda av många faktorer.) - ingen modern GC-implementering använder referensräkning Swift använder automatisk referensräkning.
Svar
Eftersom det inte finns något behov av att använda C ++.
Herb Sutter:” Jag har inte skrivit ta bort på flera år. ”
se Skriva modern C ++ -kod: hur C ++ har utvecklats genom åren 21:10
Det kan överraska många erfarna C ++ – programmerare.
Kommentarer
- Intressant. Mitt läsmaterial för idag.
- Bah, en video. Men ändå intressant redan.
- intressant video. 21 minuter in och 55 minuter in var de bästa bitarna. Synd att WinRT-samtalen fortfarande såg ut att vara C ++ / CLI bumpf.
- @ dan04: Det är '. Men om du skriver i C får du det du ber om.
- Att hantera smarta pekare är inte mer krävande än att se till att du inte ' t ha onödiga referenser i en skräpuppsamlad miljö. Eftersom GC inte kan ' inte läsa dina tankar är det inte heller '.
Svar
”Allt” som en skräpsamlare är är en process som körs regelbundet för att se om det finns några icke refererade objekt i minnet och om det raderas. (Ja, jag vet att detta är en överdriven förenkling). Detta är inte en egenskap hos språket, utan ramverket.
Det finns skräpsamlare skrivna för C och C ++ – den här till exempel .
En anledning till att man inte har ”lagts” till språket kan bero på den stora volymen av befintlig kod som aldrig skulle använda den eftersom de använder sin egen kod för att hantera minne. En annan anledning kan vara att de typer av applikationer som skrivs i C och C ++ inte behöver omkostnaderna förknippade med en skräpuppsamlingsprocess.
Kommentarer
- Men framtida program skrev skulle börja använda sopuppsamlaren, nej?
- Även om insamling av skräp är teoretiskt oberoende av vilket programmeringsspråk som helst, är det ganska svårt att skriva en användbar GC för C / C ++, och till och med omöjligt att göra en idiotsäker (åtminstone lika idiotsäker som Java div id = ”0f18cfc402″>
s) – Anledningen till att Java kan dra av den är att den körs i en kontrollerad virtualiserad miljö. Omvänt är Java-språket utformat för GC, och du ' har svårt att skriva en Java-kompilator som inte ' inte gör GC .
malloc
och free
skulle du bryta mitt rätta program. free
tills jag var klar med det . Men din föreslagna skräpsamlare som inte ' t frigör minnet tills jag uttryckligen kallar free
isn ' ta skräpsamlare alls. Svar
C utformades i en tid då skräpsamlingen knappt var ett val. Det var också avsett för användning där skräpsamling vanligtvis inte skulle fungera – ren metall, realtidsmiljöer med minimalt minne och minimalt driftstöd. Kom ihåg att C var implementeringsspråket för den första unix, som kördes på en pdp-11 med 64 * K * minne. C ++ var ursprungligen en förlängning av C – valet hade redan gjorts, och det är väldigt svårt att transplantera skräpsamling på ett befintligt språk. Det är den typ av saker som måste byggas in från bottenvåningen.
Svar
Jag har inte exakta citat men både Bjarne och Herb Sutter säger något i riktning:
C ++ behöver inte en skräpsamlare, eftersom den inte har något skräp.
I modern C ++ du använder smarta pekare och har därför inget sopor.
Kommentarer
- vad är smarta pekare?
- om det var så enkelt, ingen skulle ha implementerat någon GC.
- @deadalnix: Rätt, för ingen implementerar någonting alltför komplicerat, långsamt, uppsvällt eller onödigt. All programvara är 100% effektiv hela tiden, eller hur?
- @deadalnix – C ++ – tillvägagångssättet för minneshantering är nyare än sopor. RAII uppfanns av Bjarne Stroustrup för C ++. Rengöring av förstörare är en äldre idé, men reglerna för att säkerställa exceptionell säkerhet är nyckeln. Jag vet inte ' när exakt när själva idén först beskrevs men den första C ++ standarden slutfördes 1998 och Stroustrups " Design och utveckling av C ++ " var inte ' t publicerad fram till 1994, och undantag var ett relativt nytt tillskott till C ++ – efter publiceringen av " Kommenterad C ++ referenshandbok " 1990 tror jag. GC uppfanns 1959 för Lisp.
- @deadalnix – är du medveten om att åtminstone en Java-VM använde en referensräkning GC som (nästan) kunde implementeras med C ++ – stil RAII med en smart pekarklass – just eftersom det var effektivare för flertrådad kod än befintliga virtuella datorer? Se www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf. En anledning till att du inte ' inte ser detta i C ++ i praktiken är den vanliga GC-samlingen – den kan samla cykler, men kan ' t välja en säker destruktörsordning i närvaro av cykler och kan därmed inte säkerställa tillförlitlig destruktörrensning.
Svar
Du fråga varför dessa språk inte har uppdaterats för att inkludera en valfri sopsamlare.
Problemet med valfri sopsamling är att du inte kan blanda kod som använder de olika modellerna. Det vill säga, om jag skriver kod som förutsätter att du använder en sopuppsamlare kan du inte använda den i ditt program som har avfallssamlingen avstängd. Om du gör det läcker den överallt.
Svar
Det finns olika problem, inklusive …
- Även om GC uppfanns före C ++ och möjligen före C implementerades både C och C ++ innan GC godkändes allmänt som praktiskt.
- Du kan inte enkelt implementera en GC-språk och plattform utan ett underliggande icke-GC-språk.
- Även om GC är bevisbart effektivare än icke-GC för typiska applikationskoder som utvecklats i typiska tidsskalor etc, finns det frågor där mer utvecklingsarbete är en bra handel -off och specialiserad minneshantering kommer att överträffa en allmän GC. Dessutom är C ++ påvisbart mer effektivt än de flesta GC-språk även utan någon extra utvecklingsinsats.
- GC är inte universellt säkrare än C ++ – stil RAII RAII tillåter att andra resurser än minne rensas automatiskt, i grund och botten för att de stöder tillförlitliga och snabba destruktörer. Dessa kan inte kombineras med konventionella GC-metoder på grund av problem med referenscykler.
- GC-språk har sina egna egenskaper typer av minne läckage, särskilt relaterat till minne som aldrig kommer att användas igen, men där existerande referenser existerade som aldrig har nollställts eller skrivits över. Behovet av att göra detta uttryckligen skiljer sig inte i princip från behovet av att
delete
ellerfree
uttryckligen. GC-metoden har fortfarande en fördel – inga hängande referenser – och statisk analys kan fånga vissa fall, men återigen finns det ingen perfekt lösning för alla fall.
I grund och botten delvis ” Det handlar om språkens ålder, men det kommer alltid att finnas en plats för icke-GC-språk hur som helst – även om det är lite nischigt. Och på allvar, i C ++, är bristen på GC inte ”en stor sak – ditt minne hanteras annorlunda, men det hanteras inte.
Microsofts managed C ++ har åtminstone en viss förmåga att blanda GC och icke- GC i samma applikation, vilket möjliggör en mix-and-match av fördelarna med var och en, men jag har inte erfarenheten att säga hur bra det fungerar i praktiken.
Rep-whoring länkar till relaterade svar av mig …
- 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 tänka dig att skriva en enhetshanterare på ett språk med skräpsamling? Hur många bitar kan komma ner rad medan GC kördes?
Eller ett operativsystem? Hur kan du starta skräpsamlingen innan du ens startar kärnan?
C är utformad för låg nivå nära hårdvaruuppgifterna. Problemet? är det så trevligt språk att det också är ett bra val för många högre nivåer. Språkzarsna är medvetna om dessa användningar men de måste stödja kraven på enhetsdrivrutiner, inbäddad kod och operativsystem som en prioritet.
Kommentarer
- C bra för hög nivå? Jag fnös min drink över hela mitt tangentbord.
- Tja, han sa " många högre nivåer ". Han kunde räkna med troll (en, två, många …). Och han ' t sa faktiskt högre än vad. Skämt är dock ' sant – beviset är att många viktiga projekt på högre nivå har framgångsrikt utvecklats i C. Det kan finnas bättre val nu för många av dessa projekt, men ett arbetsprojekt är starkare bevis än spekulationer om vad som kan ha varit.
- Det finns ' några hanterade operativsystem och de fungerar ganska bra. I själva verket, när du gör hela systemet hanterat, sjunker prestandan från att använda hanterad kod ännu lägre, upp till snabbare än ohanterad kod i verkliga scenarier. Naturligtvis är det alla " research OS " – där ' är ganska mycket nej sätt att göra dem kompatibla med befintlig ohanterad kod förutom att göra ett helt virtualiserat ohanterat operativsystem inom det hanterade operativsystemet. Microsoft föreslog dock någon gång att de skulle kunna ersätta Windows Server med en av dem, eftersom fler och fler serverkoder skrivs på. NET.
Svar
Det korta och tråkiga svaret på den här frågan är att det måste finnas ett icke-skräpsamlat språk där ute för de människor som skriver skräpsamlare. Det är inte begreppsmässigt lätt att ha ett språk som samtidigt möjliggör mycket exakt kontroll över minneslayouten och har en GC som körs på toppen.
Den andra frågan är varför C och C ++ inte har sopor.Tja, jag vet att C ++ har ett par av dem runt men de är inte riktigt populära eftersom de tvingas ta itu med ett språk som inte var utformat för att GC-ed i första hand och de människor som fortfarande använder C ++ i den här åldern är inte riktigt den typen som saknar en GC.
Istället för att lägga till GC till ett gammalt språk som inte är GC-ed är det faktiskt lättare att skapa ett nytt språk som har det mesta av samma syntax medan du stöder en GC. Java och C # är bra exempel på detta.
Kommentarer
- Någonstans på programmers.se eller SO, där ' en påstående någon gjorde för mig att någon arbetade med en self-bootstrapping skräp-samlade sak – IIRC implementerar i princip den virtuella datorn med ett GC-språk, med en bootstrapping-delmängd som används för att implementera GC själv Jag glömmer namnet. När jag tittade på det visade det sig att de ' i princip aldrig nådde språnget från delmängden utan GC till arbets-GC-nivån. är möjligt i princip, men AFAIK har det aldrig uppnåtts i praktiken – det ' är verkligen ett fall av att göra saker på den svåra vägen.
- @ Steve314: I ' Jag älskar att se det om du någonsin kommer ihåg var du hittade det!
- hittade det! Se kommentarerna till stackoverflow.com/questions/3317329/… med hänvisning till Klein VM. En del av problemet att hitta det – frågan stängdes.
- BTW – Jag verkar inte kunna starta mina kommentarer med @missingno – vad ger det?
- @ steve314: Har jag blivit svaret här tråd är bifogad, jag har redan fått ett meddelande om alla kommentarer. Att göra en @ -post i det här fallet skulle vara överflödig och är inte tillåten av SE (don ' t fråga mig varför dock). (Den verkliga orsaken är dock för att mitt nummer saknas)
Svar
Avfallssamling är i grunden oförenlig med en systemspråk som används för att utveckla drivrutiner för DMA-kompatibel hårdvara.
Det är helt möjligt att den enda pekaren till ett objekt lagras i ett hårdvaruregister i någon kringutrustning. Eftersom sopuppsamlaren inte vet om detta skulle det tro att objektet inte kunde nås och samla det.
Detta argument har dubbelt för att komprimera GC. Även om du var noga med att upprätthålla referenser i minnet till objekt som används av kringutrustning för hårdvara, när GC flyttade objektet, skulle den inte veta hur du uppdaterar pekaren i det perifera konfigurationsregistret.
Så nu behöver du en blandning av orörliga DMA-buffertar och GC-hanterade objekt, vilket innebär att du har alla nackdelarna med båda.
Kommentarer
- Förmodligen alla nackdelarna med båda, men färre fall av varje nackdel, och samma för fördelar. Uppenbarligen finns det komplexitet i att ha fler typer av minneshantering att hantera, men det kan också vara svårt att undvika genom att välja rätt häst för varje kurs i din kod. Sannolikt kan jag föreställa mig, men det finns ' ett teoretiskt gap där. Jag ' har spekulerat i att blanda GC och icke-GC på samma språk tidigare, men inte för enhetsdrivrutiner – mer för att ha en mestadels GC-applikation, men med lite manuellt minneshanterat lågt nivå datastrukturbibliotek.
- @ Steve314: Skulle ' inte säga att komma ihåg vilka objekt som måste frigöras manuellt är lika betungande som att komma ihåg att frigöra allt? (Självklart kan smarta pekare hjälpa till med endera, så ingen av dem är ett stort problem) Och du behöver olika pooler för manuellt hanterade objekt mot samlade / kompakterbara objekt, eftersom komprimering inte ' t fungerar bra när det finns fasta objekt spridda överallt. Så mycket extra komplexitet för ingenting.
- Inte om det finns ' en tydlig uppdelning mellan högnivåkoden som alla är GC och lågnivån kod som väljer från GC. Jag utvecklade huvudsakligen idén när jag tittade på D för några år sedan, vilket gör att du kan välja bort GC men inte ' inte låter dig välja igen. Ta till exempel ett B + trädbibliotek . Behållaren som helhet bör vara GC, men datastrukturen noder förmodligen inte – det ' är effektivare att göra en anpassad genomsökning genom bladnoderna bara än att göra GC till en rekursiv sökning genom grennoderna. Men den här skanningen behöver rapportera de innehållna objekten till GC.
- Poängen är att ' är en innehållsfunktion. Att behandla B + trädnoderna som speciell WRT-minneshantering är inte annorlunda än att behandla dem som speciella WRT som är B + trädnoder. Det ' är ett inkapslat bibliotek, och applikationskoden behöver inte ' behöver veta att GC-beteende har kringgåtts / special-cased.Förutom att det åtminstone vid den tiden var omöjligt i D – som sagt, inget sätt att välja tillbaka och rapportera innehållet till GC som potentiella GC-rötter.
Svar
Eftersom C & C ++ är relativt låga språk som är avsedda för allmänt ändamål, även till exempel att köra på en 16-bitars processor med 1 MB minne i ett inbäddat system, som inte hade råd att slösa med minne med gc.
Kommentarer
- " Inbäddat system "? När C standardiserades (1989) behövde den kunna hantera datorer med 1 MB minne.
- Jag håller med, jag citerade ett mer aktuellt exempel.
- 1 MB ??? Holy schmoley, vem skulle någonsin behöva så mycket RAM? < / billGates >
Svar
Det finns sopor i C ++ och C. Inte säker på hur detta fungerar i C, men i C ++ kan du använda RTTI för att dynamiskt upptäcka ditt objektdiagram och använda det för insamling av skräp.
Såvitt jag vet kan du inte skriva Java utan sopuppsamlare. En liten sökning dök upp detta .
Nyckelskillnaden mellan Java och C / C ++ är att i C / C ++ är valet alltid ditt , medan du i Java ofta lämnar utan alternativ efter design.
Kommentarer
- Och också att de dedikerade sopuppsamlarna är bättre implementerade, effektivare och passar bättre in i språket. 🙂
- Nej, du kan ' t använder RTTI för att dynamiskt upptäcka objektgrafen i C / C ++: Det ' är vanliga gamla dataobjekt som förstör allt. Det finns helt enkelt ingen RTTI-information lagrad i ett vanligt gammalt dataobjekt som gör det möjligt för en skräpsamlare att skilja mellan pekare och icke-pekare i det objektet. Ännu värre, pekare behöver inte vara perfekt inriktade på all hårdvara, så med tanke på ett 16 byte-objekt finns det 9 möjliga platser där en 64-bitars pekare kan lagras, varav bara två inte ' t överlappar varandra.
Svar
Det är en avvägning mellan prestanda och säkerhet.
Det finns ingen garanti för att ditt skräp kommer att samlas in i Java, så det kan hänga med att använda utrymme under lång tid, medan skanningen efter icke refererade objekt (dvs. sopor) också tar längre tid än att uttryckligen radera eller frigöra ett oanvänt objekt.
Fördelen är naturligtvis att man kan bygga ett språk utan pekare eller utan minnesläckor, så det är mer sannolikt att man producerar rätt kod.
Det kan finnas en liten ”religiös” kant till dessa debatter ibland – varnas!
Svar
Här är en lista över inneboende problem med GC, vilket gör det oanvändbart i ett systemspråk som C:
-
GC måste springa under nivån för koden vars objekt den hanterar. Det finns helt enkelt ingen sådan nivå i en kärna.
-
En GC måste stoppa den hanterade koden då och då. Tänk nu på vad som skulle hända om det gjorde det mot din kärna. All bearbetning på din maskin skulle stanna i exempelvis millisekunder medan GC skannar alla befintliga minnestilldelningar. Detta skulle döda alla försök att skapa system som fungerar under strikta realtidskrav.
-
En GC måste kunna skilja mellan pekare och icke-pekare. Det vill säga, det måste kunna titta på varje minnesobjekt som finns och kunna producera en lista med förskjutningar där dess pekare finns.
Denna upptäckt måste vara perfekt: GC måste kunna att jaga alla pekare den upptäcker. Om det avledde ett falskt positivt skulle det troligen krascha. Om det misslyckades med att upptäcka ett falskt negativt skulle det troligtvis förstöra ett objekt som fortfarande används, krascha den hanterade koden eller tyst skada dess data.
Detta kräver absolut att typinformation lagras i varje enskild objekt som existerar. Både C och C ++ tillåter emellertid vanliga gamla dataobjekt som inte innehåller någon typinformation.
-
GC är ett naturligt långsamt företag. Programmerare som har socialiserats med Java kanske inte inser detta, men program kan vara storleksordningar snabbare när de inte implementeras i Java. Och en av de faktorer som gör Java långsam är GC. Detta är vad som hindrar GCed-språk som Java från att användas i superdator. Om din maskin kostar en miljon per år i energiförbrukning, du vill inte betala ens 10% av det för skräpsamling.
C och C ++ är språk som har skapats för att stödja alla möjliga användningsfall. Och som du ser är många av dessa användningsfall uteslutna av skräpsamling. Så, för att stödja dessa användningsfall kan C / C ++ inte samlas i skräp.