Închis . Această întrebare trebuie să fie mai concentrată
. În prezent, nu acceptă răspunsuri.
Comentarii
Răspuns
Colectarea deșeurilor necesită structuri de date pentru urmărirea alocațiilor și / sau numărarea referințelor. Acestea creează cheltuieli generale în memorie, performanță și complexitatea limbajului. C ++ este conceput pentru a fi „aproape de metal”, cu alte cuvinte, are partea de performanță mai ridicată a caracteristicilor de compromis față de comoditate. Alte limbi fac acest compromis diferit. Aceasta este una dintre considerațiile în alegerea unei limbi, pe care accentul îl preferați.
Acestea fiind spuse, există o mulțime de scheme de numărare a referințelor în C ++, care sunt destul de ușoare și performante, dar se află în biblioteci, atât comerciale, cât și open source, mai degrabă decât parte a limbajului în sine. Numărarea referințelor pentru gestionarea duratei de viață a obiectelor nu este aceeași cu colectarea gunoiului, dar abordează multe dintre aceleași tipuri de probleme și se potrivește mai bine cu abordarea de bază a C ++.
Comentarii
Răspuns
Strict vorbind, nu există deloc gestionarea memoriei în limbajul C. malloc () și free () nu sunt cuvinte cheie în limbă, ci doar funcții care sunt apelate dintr-o bibliotecă.Această distincție poate fi pedantă acum, deoarece malloc () și free () fac parte din biblioteca standard C și vor fi furnizate de orice implementare standard C conformă, dar acest lucru nu a fost întotdeauna adevărat în trecut.
De ce ați dori o limbă fără standard pentru gestionarea memoriei? Aceasta revine la originile lui C ca „asamblare portabilă”. Există multe cazuri de hardware și algoritmi care pot beneficia de, sau chiar necesita, tehnici de gestionare a memoriei specializate. Din câte știu, nu există nicio modalitate de a dezactiva complet gestionarea memoriei native Java și de a o înlocui cu propria dvs. Acest lucru pur și simplu nu este acceptabil în unele situații de înaltă performanță / resurse minime. C oferă o flexibilitate aproape completă pentru a alege exact ce infrastructură programul dvs. va fi folosit. Prețul plătit este că limbajul C oferă foarte puțin ajutor în scrierea unui cod corect, fără erori.
Comentarii
s Java ". .NET poate face cam tot ce poate C – rămâne doar în urma capacităților native C ++ ' (de exemplu, clasele sunt gestionate numai în .NET). Desigur, aveți și C ++. NET, care are tot ceea ce face C ++ și tot ceea ce face .NET.
@Luaan Am ' spun că ' o definiție foarte generoasă de a avea " gestionarea memoriei " " Până când începeți să alocați din heap, ' sunteți bine și dandy. ' este alocarea grămezii care încurcă lucrurile ", ceea ce le place să spună ' o mașină este un avion perfect bun, nu este doar ' capabilă să zboare.
@ CharlesE.Grant Ei bine, un limbaj pur funcțional poate face totul cu asta un fel de gestionare a memoriei. Doar pentru că alocarea heap-ului este un compromis bun în unele cazuri de utilizare, nu ' înseamnă că ' este reperul pentru toate limbile / timpii de rulare . ' nu pare că gestionarea memoriei încetează să fie " gestionarea memoriei " doar pentru că ' s simplu, direct, ascuns în culise. Proiectarea alocării de memorie statică este în continuare gestionarea memoriei, la fel ca o bună utilizare a stivei și a oricăror alte lucruri pe care le aveți la dispoziție.
" orice implementare conformă standard " nu este adevărat, numai pentru implementarea standard a mediului gazdă compatibil. Unele platforme / biblioteci standard, majoritatea pentru microcontroler încorporat pe 8 sau 16 biți, nu furnizează malloc()
sau free()
. (de exemplu sunt MLAP-Compilers for PIC)
Răspuns
Răspunsul real este că singurul mod de a face un mecanism sigur și eficient de colectare a gunoiului este să aibă suport la nivel de limbă pentru referințe opace. (Sau, dimpotrivă, o lipsă de suport la nivel de limbaj pentru manipularea directă a memoriei.)
Java și C # o pot face deoarece au tipuri de referință speciale care nu pot fi manipulate. Acest lucru oferă timpului de rulare libertatea de a face lucruri precum mutarea obiectelor alocate în memorie , ceea ce este crucial pentru o implementare GC performant .
Pentru înregistrare, nicio implementare GC modernă nu folosește numărarea referințelor , deci este complet roșu hering. GC-urile moderne folosesc colecția generațională, în care noile alocări sunt tratate în esență în același mod în care alocările stivei sunt într-un limbaj precum C ++ și apoi periodic orice obiecte nou alocate care sunt încă în viață sunt mutate într-un spațiu separat „supraviețuitor” și o întreagă generație obiectelor este repartizat imediat.
Această abordare are avantaje și dezavantaje: avantajul este că alocările heap într-un limbaj care acceptă GC sunt la fel de rapide ca alocările stivei într-un limbaj care nu acceptă GC, iar dezavantajul este că obiectele care trebuie să efectueze curățarea înainte de a fi distruse fie necesită un mecanism separat (de exemplu, C #” s using
cuvânt cheie) sau codul lor de curățare rulează nedeterministic.
Rețineți că o cheie pentru un GC performant este că trebuie să existe suport pentru limbă pentru o clasă specială de referințe. C nu are acest suport de limbaj și nu va avea niciodată; deoarece C ++ are o supraîncărcare a operatorului, ar putea emula un tip de pointer GC, deși ar trebui făcut cu atenție. De fapt, atunci când Microsoft și-a inventat dialectul C ++ care va rula sub CLR (timpul de execuție .NET), au trebuit să inventeze o nouă sintaxă pentru „C # -styles reference” (de ex. >) pentru a le distinge de „referințe în stil C ++” (de ex. Foo&
).
Ceea ce are C ++ și ceea ce este utilizat în mod regulat de programatorii C ++, este indicatori inteligenți , care sunt într-adevăr doar un mecanism de numărare a referințelor. Nu aș considera contorizarea referințelor ca fiind „adevărat” GC, dar oferă multe dintre aceleași beneficii, cu prețul unei performanțe mai lente decât gestionarea manuală a memoriei sau GC adevărat, dar cu avantajul distrugerii deterministe.
La sfârșitul zilei, răspunsul se rezumă într-adevăr la o caracteristică de proiectare a limbii. C a făcut o singură alegere, C ++ a făcut o alegere care i-a permis să fie compatibilă înapoi cu C, oferind totuși alternative suficient de bune pentru cele mai multe scopuri, iar Java și C # au făcut o alegere diferită, care este incompatibilă cu C, dar este, de asemenea, suficient de bună pentru majoritatea scopurilor. Din păcate, nu există niciun glonț de argint, dar familiarizarea cu diferitele alegeri de acolo vă va ajuta să alegeți cea corectă pentru orice program pe care încercați să-l creați în prezent.
Comentarii
Răspuns
Răspuns
„Tot” este un colector de gunoi este un proces care rulează periodic pentru a vedea dacă există obiecte neriferențiate în memorie și dacă există ștergerea acestora. (Da, știu că este o simplificare excesivă brută). Aceasta nu este o proprietate a limbajului, ci cadrul.
Există colectoare de gunoi scrise pentru C și C ++ – acesta de exemplu .
Unul dintre motivele pentru care nu s-a „adăugat” limbii ar putea fi din cauza volumului mare de cod existent care nu l-ar folosi niciodată, deoarece folosesc propriul cod pentru gestionarea memoriei. Un alt motiv ar putea fie că tipurile de aplicații scrise în C și C ++ nu au nevoie de cheltuieli generale asociate cu un proces de colectare a gunoiului.
Comentarii
Răspuns
C a fost conceput într-o eră în care colectarea gunoiului abia a fost o optiune. De asemenea, a fost destinat utilizărilor în care colectarea gunoiului nu ar funcționa în general – metale goale, medii în timp real, cu memorie minimă și suport minim de rulare. Amintiți-vă că C a fost limbajul de implementare pentru primul unix, care a rulat pe un pdp-11 cu 64 * K * octeți de memorie. C ++ a fost inițial o extensie la C – alegerea fusese deja făcută și este foarte greu să grefezi colectarea gunoiului într-un limbaj existent. Este genul de lucruri care trebuie să fie încorporat de la parter.
Răspuns
Nu am ghilimelele exacte, dar atât Bjarne, cât și Herb Sutter spun ceva de-a lungul liniei:
C ++ nu are nevoie de un colector de gunoi, deoarece nu are gunoi.
În modern C ++ folosești indicatori inteligenți și, prin urmare, nu ai gunoi.
Comentarii
Răspuns
Tu întrebați de ce aceste limbi nu au fost actualizate pentru a include un colector de gunoi opțional.
Problema cu colectarea de gunoi opțional este că nu puteți amesteca codul care utilizează diferitele modele. Adică, dacă scriu cod care presupune că utilizați un colector de gunoi, nu îl puteți folosi în programul dvs. care are colectarea gunoiului dezactivată. Dacă faceți acest lucru, acesta se va scurge peste tot.
Răspuns
Există diverse probleme, inclusiv …
- Deși GC a fost inventat înainte de C ++ și, eventual, înainte de C, atât C cât și C ++ au fost implementate înainte ca GC să fie acceptate pe scară largă ca fiind practice.
- Nu puteți implementa cu ușurință un Limbaj și platformă GC fără un limbaj non-GC subiacent.
- Deși GC este demonstrabil mai eficient decât non-GC pentru codul de aplicații tipice dezvoltat în perioade de timp tipice etc., există probleme în care efortul de dezvoltare mai mare este un comerț -off și gestionarea de memorie specializată vor depăși performanța unui GC de uz general. În plus, C ++ este de obicei demonstrabil mai eficient decât majoritatea limbajelor GC, chiar și fără niciun efort de dezvoltare suplimentar.
- GC nu este universal mai sigur decât RAII în stil C ++ . RAII permite curățarea automată a resurselor, altele decât memoria, în esență, deoarece acceptă destructori fiabili și în timp util. Acestea nu pot fi combinate cu metodele convenționale GC din cauza problemelor legate de ciclurile de referință. feluri de memorie scurgeri, în special referitoare la memorie care nu va mai fi folosită niciodată, dar acolo unde au existat referințe existente care nu au fost niciodată anulate sau suprascrise. Nevoia de a face acest lucru în mod explicit nu diferă în principiu de necesitatea
delete
sau free
în mod explicit. Abordarea GC are încă un avantaj – fără referințe atârnate – și analiza statică poate surprinde unele cazuri, dar, din nou, „nu există o soluție perfectă pentru toate cazurile.
Practic, parțial” Este vorba despre vârsta limbilor străine, dar oricum va exista întotdeauna un loc pentru limbile non-GC – chiar dacă este un loc cam de nișă. Și, serios, în C ++, lipsa GC nu este o problemă – memoria dvs. este gestionată diferit, dar nu este gestionată.
Microsofts gestionat C ++ are cel puțin o anumită abilitate de a amesteca GC și non- GC în aceeași aplicație, permițând o combinație a avantajelor de la fiecare, dar nu am experiența de a spune cât de bine funcționează acest lucru în practică.
a mea …
Răspuns
Vă puteți imagina scrierea unui dispozitiv de manipulare într-o limbă cu colectarea gunoiului? Câți biți ar putea coborî linie în timp ce GC rulează?
Sau un sistem de operare? Cum ați putea începe să ruleze colectarea gunoiului înainte de a porni chiar nucleul?
C este conceput pentru un nivel scăzut, aproape de sarcinile hardware. Problema? este un limbaj atât de frumos încât este o alegere bună și pentru multe sarcini de nivel superior. Czarile de limbă sunt conștiente de aceste utilizări, dar trebuie să susțină cerințele driverelor de dispozitiv, codului încorporat și sistemelor de operare ca prioritate.
Comentarii
Răspuns
Răspunsul scurt și plictisitor la această întrebare este că trebuie să existe un limbaj non-gunoi colectat acolo pentru persoanele care scriu colectorii de gunoi. Nu este ușor din punct de vedere conceptual să ai un limbaj care să permită în același timp un control foarte precis asupra aspectului memoriei și are un GC rulat deasupra.
Cealaltă întrebare este de ce C și C ++ nu au colectoare de gunoi.Ei bine, știu că C ++ are câteva dintre ele în jur, dar nu sunt foarte populare deoarece sunt forțate să se ocupe de un limbaj care nu a fost conceput pentru a fi GC-ed, în primul rând, și persoanele care încă folosesc C ++ în această vârstă nu este cu adevărat de genul căruia îi lipsește un GC.
De asemenea, în loc să adăugați GC într-un limbaj vechi care nu este GC, este de fapt mai ușor să creați un nou limbaj care are cea mai mare parte a aceeași sintaxă în timp ce acceptă un GC. Java și C # sunt exemple bune în acest sens.
Comentarii
Răspuns
Colectarea gunoiului este fundamental incompatibilă cu un limbajul sistemelor utilizat pentru dezvoltarea driverelor pentru hardware compatibil DMA.
Este complet posibil ca singurul indicator al unui obiect să fie stocat într-un registru hardware într-un anumit periferic. Deoarece colectorul de gunoi nu ar ști despre acest lucru, s-ar crede că obiectul nu poate fi accesat și l-ar colecta.
Acest argument are un dublu pentru compactarea GC. Chiar dacă ați avea grijă să mențineți referințe în memorie la obiecte utilizate de periferice hardware, atunci când GC a mutat obiectul, nu ar ști cum să actualizeze pointerul din registrul de configurare periferic. acum ai avea nevoie de un amestec de tampoane DMA imobile și obiecte gestionate de GC, ceea ce înseamnă că ai toate dezavantajele ambelor.
Comentarii
Răspuns
Deoarece, C & C ++ sunt limbaje de nivel relativ scăzut destinate scopului general, chiar, de exemplu, pentru a rula pe un procesor de 16 biți cu 1 MB de memorie într-un sistem încorporat, care nu-și permitea risipirea memoriei cu gc.
Comentarii
Răspuns
Există colectoare de gunoi în C ++ și C. Nu sunt sigur cum funcționează acest lucru în C, dar în C ++ poți folosi RTTI pentru a descoperi dinamic graficul obiectelor și a-l utiliza pentru colectarea gunoiului.
Din câte știu, nu poți scrie Java fără un colector de gunoi. O mică căutare a apărut aceasta .
Diferența cheie între Java și C / C ++ este că în C / C ++ alegerea este întotdeauna a ta , întrucât în Java „rămâneți adesea fără opțiuni prin design.
Comentarii
Răspuns
Este „un compromis între performanță și siguranță.
Nu există nicio garanție că gunoiul dvs. va fi colectat în Java, deci poate fi agățat folosind spațiu pentru o lungă perioadă de timp, în timp ce scanarea obiectelor neriferențiate (adică gunoiul) durează, de asemenea, mai mult decât ștergerea explicit sau eliberarea unui obiect neutilizat.
Avantajul este, desigur, că se poate construi un limbaj fără indicatori sau fără scurgeri de memorie, deci este mai probabil să producă un cod corect.
Uneori poate exista o ușoară margine „religioasă” pentru aceste dezbateri – fiți atenți!
Răspuns
Iată o listă a problemelor inerente ale GC, care o fac inutilizabilă într-un limbaj de sistem precum C:
-
GC trebuie să ruleze sub nivelul codului ale cărui obiecte le administrează. Pur și simplu nu există un astfel de nivel într-un nucleu.
-
Un GC trebuie să oprească codul gestionat din când în când. Acum gândiți-vă la ce s-ar întâmpla dacă ar face asta cu nucleul dvs. Toate procesările de pe aparatul dvs. se vor opri, să zicem, o milisecundă, în timp ce GC scanează toate alocările de memorie existente. Acest lucru ar distruge toate încercările de a crea sisteme care funcționează în conformitate cu cerințe stricte în timp real.
-
Un GC trebuie să poată distinge între pointeri și non-pointeri. Adică, trebuie să fie capabil să privească fiecare obiect de memorie existent și să poată produce o listă de compensări în care pot fi găsiți indicii săi.
Această descoperire trebuie să fie perfectă: GC trebuie să poată pentru a urmări toate indicațiile pe care le descoperă. Dacă ar dereferenția un fals pozitiv, probabil s-ar prăbuși. Dacă nu reușea să descopere un negativ fals, probabil că ar distruge un obiect care este încă în uz, blocând codul gestionat sau corupându-și datele în tăcere.
Acest lucru necesită în mod absolut ca informațiile de tip să fie stocate în fiecare obiect existent. Cu toate acestea, atât C, cât și C ++ permit obiecte de date vechi simple, care nu conțin informații de tip.
-
GC este o afacere inerent lentă. Programatorii care au fost socializați cu Java s-ar putea să nu realizeze acest lucru, dar programele pot fi ordine de mărime mai rapide atunci când nu sunt implementate în Java. Și unul dintre factorii care fac Java lent să fie GC. Acesta este ceea ce împiedică utilizarea limbajelor GCed, cum ar fi Java, în supercomputere. costă un milion pe an în consum de energie, nu doriți să plătiți nici măcar 10% din asta pentru colectarea gunoiului.
C și C ++ sunt limbaje create pentru a suporta toate cazurile de utilizare posibile. Și, după cum vedeți, multe dintre aceste cazuri de utilizare sunt excluse de colectarea gunoiului. Deci, pentru a susține aceste cazuri de utilizare, C / C ++ nu poate fi colectat gunoi.