Garbage collection

Da Wikipedia, l'enciclopedia libera.

In informatica per garbage collection (letteralmente raccolta dei rifiuti, a volte abbreviato con GC) si intende una modalità automatica di gestione della memoria, mediante la quale un sistema operativo, o un compilatore e un modulo di run-time, liberano le porzioni di memoria che non dovranno più essere successivamente utilizzate dalle applicazioni. In altre parole, il garbage collector annoterà le aree di memoria non più referenziate, cioè allocate da un processo attivo, e le libererà automaticamente. La garbage collection è stata inventata da John McCarthy intorno al 1959 per il linguaggio di programmazione Lisp.[1][2]

Questo meccanismo porta ad un notevole cambio nello stile di programmazione dei linguaggi che lo implementano. Infatti non è più possibile richiedere esplicitamente di liberare la memoria utilizzata da un oggetto, ovvero terminare tale oggetto in modo deterministico, ma si lascia che il sistema esegua questa operazione automaticamente, nel momento in cui lo riterrà più opportuno per migliorare le prestazioni complessive (finalizzazione non deterministica).

Descrizione[modifica | modifica sorgente]

Per la gestione della memoria si tiene conto di due principi fondamentali:

  1. trovare gli oggetti in un programma ai quali non sarà più possibile accedere in futuro;
  2. recuperare le risorse che sono state utilizzate da questi oggetti.

Attuando il processo di garbage collection, l'ambiente nel quale viene eseguito il programma gestisce la memoria automaticamente, liberando il programmatore dalla necessità di prevedere quando rilasciare le risorse utilizzate da un oggetto non più necessario all'elaborazione. La garbage collection inoltre migliora la stabilità dei programmi, in quanto consente di evitare quella classe di bug, connessi alla necessità di manipolare direttamente, da parte del programmatore, i puntatori alle varie aree di memoria che contenevano gli oggetti utilizzati durante l'esecuzione, ma già rilasciati per altri usi (problema dei 'dangling pointers').

Alcuni linguaggi di programmazione, come Java, Python e C# (.NET), hanno un sistema di garbage collection integrato direttamente nell'ambiente di esecuzione, mentre per altri linguaggi, come il C e il C++, la sua eventuale implementazione è a carico del programmatore. Tuttavia molti linguaggi usano una combinazione dei due approcci, come Ada, Modula-3 e CLI che sono garbage-collected, ma consentono all'utente di eliminare manualmente gli oggetti o, volendo velocizzare il processo, disattivare il GC. In ogni caso è più efficace attuare la raccolta durante la fase di compilazione del linguaggio. La garbage collection è quasi sempre strettamente integrata con l'allocazione di memoria.

Benefici[modifica | modifica sorgente]

La garbage collection esonera il programmatore dall'eseguire manualmente l'allocazione (richiesta) e la deallocazione (rilascio) di aree di memoria, riducendo o eliminando del tutto alcune categorie di bug:

  • Dangling pointers: persistenza nel programma di puntatori che si riferiscono ad aree di memoria che contenevano oggetti, ma che sono state deallocate. Utilizzare aree di memoria deallocate può, nel migliore dei casi, provocare un errore fatale dell'applicazione, ma si possono manifestare altri problemi anche a distanza di tempo dalla effettiva deallocazione. La risoluzione di questi problemi può essere molto difficoltosa.
  • Doppia deallocazione: il programma tenta di liberare nuovamente una zona di memoria che già era stata rilasciata.
  • Alcuni tipi di memory leaks: il programma perde traccia di alcune delle aree di memoria che ha allocato (ad esempio perché il puntatore ad esse viene modificato), perdendo la possibilità di deallocarle quando non servono più. Questo tipo di problema può accumularsi nel corso dell'esecuzione del programma, portando, nel corso del tempo, all'esaurimento della memoria disponibile.

La maggior parte degli errori di programmazione nei linguaggi che non prevedono la garbage collection, o quando la stessa venga volontariamente disattivata, rientrano nei casi sopra descritti.

Svantaggi[modifica | modifica sorgente]

La garbage collection presenta tuttavia anche alcuni svantaggi:

  • Il processo consuma risorse di calcolo per tenere traccia dell'utilizzo delle varie aree di memoria e per poter decidere il momento e la quantità di memoria da liberare;
  • Il momento in cui viene effettuata la collection non è prevedibile; ciò può determinare improvvisi blocchi o ritardi nell'esecuzione. Problemi di questo genere sono inaccettabili in ambienti real-time, nel rilevamento di driver periferici, e nell'elaborazione di transazioni;
  • Analogamente, sia il momento in cui una data area di memoria viene rilasciata, sia l'ordine di rilascio delle varie aree non più utilizzate, dipendono dal particolare algoritmo implementato dal garbage collector. Si può dire che il rilascio di memoria avvenga in modo non deterministico.
  • I memory leak possono comunque verificarsi, nonostante la presenza di un GC; ciò può accadere se il programma mantiene un riferimento a oggetti che hanno esaurito il loro ciclo logico di vita nell'applicazione. La presenza di riferimenti attivi comporta l'impossibilità da parte del collector di rilevare l'area di memoria come non utilizzata[3]; ciò può verificarsi ad esempio con collezioni di oggetti. Il monitoraggio del ciclo di vita degli oggetti è una responsabilità primaria dello sviluppatore in ambienti garbage-collected.

Tracing garbage collection[modifica | modifica sorgente]

Il metodo più comune per attuare la garbage collection è il metodo del tracciamento (Tracing), che consiste nel determinare in primo luogo quali oggetti sono raggiungibili (o potenzialmente tali), per poi successivamente scartare tutti gli oggetti che non lo sono.

Raggiungibilità di un oggetto[modifica | modifica sorgente]

Un oggetto viene definito raggiungibile, in maniera ricorsiva, quando esiste un riferimento ad esso tramite un oggetto esso stesso raggiungibile. Più precisamente, un oggetto può essere raggiungibile solo in due casi:

  • Quando viene creato all'avvio del programma (oggetto globale) o di una sua sotto-procedura (oggetti di scope, creati sullo stack); l'oggetto in questione viene detto in tal caso radice;
  • Quando un altro oggetto, raggiungibile, trattiene un riferimento ad esso; in modo più formale, la raggiungibilità è una chiusura transitiva.

L'identificazione delle aree di memoria spazzatura con quelle non raggiungibili non è ottimale, in quanto potrebbe accadere che un programma utilizzi per l'ultima volta una certa area molto prima che questa diventi irraggiungibile. A volte si distingue perciò fra spazzatura sintattica, quando l'oggetto non può essere raggiunto dal programma, e semantica, quando il programma non vuole più utilizzare l'oggetto. Ad esempio:

Object x = new Foo();
Object y = new Bar();
x = new Quux();
/* Da questo punto l'oggetto Foo, originariamente
 * assegnato ad x, non può più essere referenziato: 
 * Foo è un oggetto spazzatura sintattico
 */
 
if(x.check_something())
{
    x.do_something(y);
}
System.exit(0);
/* Nel blocco condizionale, y potrebbe essere spazzatura semantica, ma non
 * possiamo dirlo finché x.check_something() non termini restituendo un
 * valore; ciò sempre ammesso che effettivamente termini in un tempo finito
 */

Il problema di individuare precisamente la spazzatura semantica è purtroppo solo parzialmente decidibile: dall'esempio mostrato sopra, infatti, è chiaro che l'identificazione positiva di un oggetto come spazzatura semantica dipende dal fatto che le elaborazioni precedenti terminino correttamente in un tempo finito. Ciò comporta che un collector che volesse identificare la spazzatura semantica dovrebbe poter decidere, sempre in un tempo finito, se una certa procedura termini (problema della fermata). Pertanto, essenzialmente tutti i collectors implementati si concentrano sulla spazzatura sintattica.

Algoritmo di base[modifica | modifica sorgente]

I Tracing collector sono cosiddetti perché tracciano il set di lavoro della memoria, effettuando la raccolta degli oggetti non più necessari in cicli. Un ciclo viene avviato quando il GC stabilisce che ha bisogno di recuperare memoria e ciò accade più frequentemente quando il sistema è in memoria bassa. Il metodo originale prevede un mark-and-sweep in cui il set di memoria è toccato più volte.

Naïve mark-and-sweep[modifica | modifica sorgente]

Nel mark-and-sweep ogni oggetto in memoria ha un flag (in genere un bit) riservato esclusivamente per l'utilizzo del GC. Quando l'oggetto viene creato il flag viene posto come 'non in uso' (flag clear). Durante la prima fase (fase MARK) del ciclo di GC viene scorso l'intero set di 'root' ponendo ogni oggetto come 'in uso' (flag set). Tutti gli oggetti accessibili dalla radice del set sono anch'essi contrassegnati come 'in uso'. Nella seconda fase (fase SWEEP) ogni oggetto in memoria viene ancora una volta esaminato, quelli che hanno ancora il flag 'non in uso' non sono raggiungibili da nessun programma o dato e la loro memoria viene quindi liberata. Per gli oggetti che sono marcati 'in uso', il flag viene posto a 'non in uso', preparandoli per il prossimo ciclo di GC.

Questo metodo ha diversi svantaggi, tra i più rilevanti è che l'intero sistema viene sospeso durante la GC in modo non sempre prevedibile e per periodi di tempo non determinabili a priori; questo tipo di comportamento può creare grossi problemi in ambienti che necessitano di basse latenze di risposta o in sistemi real-time o mission critical, con possibili malfunzionamenti/deadlock/arresti che possono compromettere l'intero sistema. Inoltre, tutta la memoria di lavoro deve essere esaminata (minimo due volte) causando potenzialmente problemi nei sistemi con memoria paginata.

Tri-colour marking[modifica | modifica sorgente]

A causa di questi svantaggi i più moderni GC attuano varianti rispetto a semplici meccanismi quali mark-and-sweep, applicando algoritmi del tipo tri-colour marking. L'algoritmo effettua marcature su tre diversi livelli secondo le seguenti fasi:

  1. Crea set di livelli di bianco, grigio e nero utilizzati per segnare i vari progressi durante il ciclo.
    • Il set bianco è l'insieme di oggetti che sono candidati per essere riciclati.
    • Il set nero è l'insieme di oggetti che non hanno riferimenti in uscita a oggetti nel set bianco, e sono raggiungibile dalla radice. Gli oggetti del set nero non sono candidati per essere riciclati; in molte implementazioni, il set nero inizia come vuoto.
    • Il set grigio contiene tutti gli oggetti raggiungibili dalla radice, ma che devono ancora essere scanditi per controllare se hanno riferimenti in uscita agli oggetti "bianchi". Dal momento che sono noti per essere raggiungibile dalla radice, non possono essere riciclati e finiranno nel set nero dopo essere stati sottoposti a scansione. Il set grigio è inizializzato con gli oggetti che sono direttamente riferiti dalla radice; in genere tutti gli altri oggetti sono inizialmente posizionati nel set bianco.
    • Gli oggetti possono passare soltanto dal bianco al grigio e dal grigio al nero ma non in senso opposto.
  2. Raccoglie gli oggetti dal set di grigio e sposta questi nel set di nero (Blacken) se questi non possono essere GC.
  3. Ripete i vari passaggi fino a quando il set di grigio diventa vuoto.
  4. Quando non vi sono più oggetti nel set di grigio, per tutti i rimanenti oggetti nel set bianco è stato dimostrato che non sono raggiungibili per cui lo spazio di memoria da essi occupato viene recuperato.

Dal momento che tutti gli oggetti non immediatamente raggiungibili dalla radice sono tipicamente assegnati al set di bianco, e gli oggetti possono muoversi solo dal bianco al grigio e dal grigio al nero, l'algoritmo conserva un invariante importante - nessun oggetto nero punta direttamente ad un oggetto bianco. Questo garantisce che gli oggetti bianchi possono essere distrutti in modo sicuro una volta che il set grigio è vuoto.

L'algoritmo presenta un vantaggio importante: può essere eseguito 'on-the-fly' senza che sia arrestato il sistema per periodi di tempo significativo. Ciò si ottiene marcando gli oggetti nel momento in cui vengono allocati e durante le modifiche, mantenendo i tre insiemi. Monitorando la dimensione degli insiemi, il sistema può effettuare garbage collection periodicamente o quando necessario. Inoltre, viene eliminata la necessità di toccare l'intero insieme degli oggetti durante ciascun ciclo di GC.

Strategia di attuazione[modifica | modifica sorgente]

Al fine di attuare l'algoritmo tri-colour marking si prendono importanti decisioni al momento della progettazione e ciò può incidere sensibilmente sulle caratteristiche delle prestazioni del garbage collector.

Movimento vs non movimento[modifica | modifica sorgente]

Una volta che il set è stato classificato irraggiungibile, il GC può semplicemente rilasciare gli oggetti irraggiungibili oppure copiare alcuni o tutti gli oggetti raggiungibili in una nuova area di memoria, aggiornando tutti i riferimenti a tali oggetti come necessario. Questi sono chiamati rispettivamente collettor in non movimento ed in movimento.

A prima vista una strategia di GC in movimento può sembrare inefficiente e costosa rispetto all'approccio di non movimento, dato che sembra essere richiesto molto più lavoro per ogni ciclo. In realtà, la strategia in movimento porta a diversi vantaggi in termini di prestazioni sia durante il ciclo di raccolta dei rifiuti che durante l'esecuzione del programma vero e proprio:

  • Non è necessario ulteriore lavoro per recuperare lo spazio liberato dagli oggetti irraggiungibili, l'intera regione viene così considerata libera. Viceversa un GC non movimento deve controllare ogni oggetto irraggiungibile e registrare che la memoria occupata da essi sia disponibile.
  • Dal momento che grandi regioni contigue della memoria sono generalmente messe a disposizione dalla strategia di GC in movimento, i nuovi oggetti possono essere attribuiti semplicemente incrementando una locazione di memoria. Una strategia di non movimento invece può dopo qualche tempo, portare ad un heap fortemente frammentato, che richiede una consultazione più frequente dei piccoli blocchi di memoria disponibili al fine di allocare questi nuovi oggetti.
  • Oggetti che fanno riferimento l'uno all'altro spesso possono essere spostati molto vicini in memoria, aumentando la probabilità che questi si trovino sulla stessa linea della cache o della pagina di memoria virtuale. Questo accelererà notevolmente l'accesso ai nuovi oggetti attraverso i riferimenti.

Uno svantaggio del Garbage collection in movimento è che consente l'accesso solo attraverso i riferimenti che sono gestiti dai riferimenti dei rifiuti e non consente l'aritmetica dei puntatori. Ciò accade perché i puntatori iniziali non sono più validi dal momento in cui il GC sposta l'oggetto (diventeranno puntatori sospesi). Per l'interaoperabilità con il codice nativo, il GC deve copiare la posizione dei contenuti dell'oggetto al di fuori della regione di memoria che contiene i rifiuti. Un approccio alternativo è quello si salvare l'oggetto in memoria con un pin, impedendo al GC di muoversi e consentendo ai puntatori nativi di lavorare direttamente con la memoria ed eventualmente consentendo l'aritmetica dei puntatori.[4]

Copying vs. mark-and-sweep vs. mark-and-don't-sweep[modifica | modifica sorgente]

Per raffinare ulteriormente la distinzione, i collettor possono tracciare gli oggetti secondo tre set (bianco, grigio e nero) e mantenerli durante il ciclo di raccolta. L'approccio più semplice è il semi-space collector che risale al 1969. In questo schema di GC in movimento, la memoria è divisa in due parti: "dallo spazio" e "allo spazio". Inizialmente gli oggetti sono assegnati "allo spazio" fino a quando non diventeranno oggetti a pieno titolo e la collezione viene attivata. All'inizio lo stato "allo spazio" diventa "dallo spazio" e viceversa, e gli oggetti raggiungibili dalla radice vengono copiati dallo spazio allo spazio. Questi oggetti vengono scansionati a turno e tutti gli oggetti a cui puntano vengono copiati allo spazio fino a quando tutti gli oggetti raggiungibili sono stati copiati in questa parte. Questo approccio ha il vantaggio di essere semplice concettualmente (i tre set sono costruiti durante il processo di copia), ma uno svantaggio è che ad ogni ciclo di raccolta viene richiesta una grande regione contigua di memoria libera. La tecnica è conosciuta anche come stop-and-copy. Un ulteriore miglioramento rispetto al semi-space collector è l'algoritmo di Cheney.

Un mark-and-sweep garbage collection mantiene uno o due bit per ogni oggetto da registrare. L'albero di riferimento viene attraversato nel corso di un ciclo di raccolta (fase di mark) e gli oggetti vengono manipolati dal colletor per riflettere lo stato attuale e la fase di sweep libera la memoria. Il mark-and-sweep ha il vantaggio che una volta determinato il set irraggiungibile, non può essere attuata ne una strategia di movimento che di non movimento.

Un mark-and-don't-sweep garbage collection come il precedente, mantiene un bit per ogni oggetto da registrare, vi sono però due differenze fondamentali. Innanzitutto il set di bianco e nero hanno significato diverso da quello del mark-and-sweep, poiché in quest'ultimo sistema tutti gli oggetti raggiungibili sono sempre di colore nero. Un oggetto contrassegnato come nero rimarrà tale anche se diventa irraggiungibile. Un oggetto bianco è attribuito come inutilizzabile. In secondo luogo l'interpretazione di nero/bianco può variare (0=bianco, 1= nero) e viceversa.

Generational GC (Ephemeral GC)[modifica | modifica sorgente]

È stato osservato che in molti programmi gli oggetti creati più recentemente sono anche quelli con più probabilità di diventare rapidamente irraggiungibili (noto come Ephemeral o Generational GC). L'ipotesi generazionale divide gli oggetti in generazioni. Inoltre il sistema di runtime mantiene la conoscenza di tutti i riferimenti tenendo traccia dalla loro creazione alla sovrascrittura di riferimenti. Quando il GC va in esecuzione può essere in grado di utilizzare tale conoscenza per dimostrare che alcuni oggetti inizialmente nel set iniziale bianco non sono raggiungibili senza dover attraversare l'intera struttura di riferimento. Al fine di attuare questo concetto, molti GC generazionali utilizzano aree di memoria separate per i diversi livelli degli oggetti. Quando una regione è piena, i pochi oggetti che sono referenziati nella vecchia memoria sono promossi (copiati) nella regione immediatamente successiva e l'intera regione può essere sovrascritta con nuovi oggetti. Questa tecnica permette di incrementare la velocità, in quanto la raccolta dei rifiuti di una sola regione avviene nello stesso momento.

Generational Garbage collection è un approccio euristico e alcuni oggetti irraggiungibili non possono essere recuperati ad ogni ciclo. Talvolta può quindi essere necessario recuperare tutto lo spazio disponibile. In effetti, i sistemi di runtime per i moderni linguaggi di programmazione (come java) di solito usano alcune varianti delle diverse strategie che sono state descritte sino ad ora.

Stop-the-world vs. incremental vs. concurrent[modifica | modifica sorgente]

Il meccanismo stop-the-world opera semplicemente interrompendo l'esecuzione del ciclo di raccolta in modo da garantire che i nuovi oggetti non siano assegnati e non diventino improvvisamente irraggiungibili mentre il collector è in esecuzione. Svantaggio evidente è che il programma non può svolgere alcun lavoro utile durante mentre è in esecuzione il ciclo di raccolta (detta "embarrassing pause"). Incremental and concurrent garbage collection sono progettati per ridurre questa interruzione, svolgendo il ciclo di raccolta rifiuti in fasi distinte rispetto all'esecuzione del programma. L'idea di progettazione è quella di garantire che il programma non interferisca con il GC e viceversa.

Precise vs. conservative and internal pointers[modifica | modifica sorgente]

Alcuni collezionisti in esecuzioni in particolari ambienti possono identificare correttamente tutti i puntatori (riferimenti) di un oggetto che sono perciò detti 'precisi', contrariamente ai collezionisti conservatori. Quest'ultimi suppongono che una qualsiasi sequenza di bit in memoria potrebbe essere un puntatore che punta un qualsiasi oggetto allocato. Un esempio in cui il GC conservatore è necessario è il linguaggio di programmazione C che alloca i puntatori (non void) applica un cast di tipo (void) e viceversa.

Una problematica correlata è quella di internal pointers o puntatori a campi all'interno di un oggetto. Se la semantica di un linguaggio permette puntatori interni e quindi ci possono essere molti indirizzi che si riferiscono allo stesso oggetto, si rende difficile determinare quando un oggetto è o meno rifiuto. Un esempio è il c++, in cui l'ereditarietà multipla può causare che puntatori si riferiscono ad oggetti di base con indirizzi diversi. Anche in linguaggi come java, tuttavia, i puntatori interni possono durante il calcolo, per esempio nel riferirsi ad un array, riscontrare problemi e in un programma ben ottimizzato il puntatore corrispondente all'oggetto stesso potrebbe essere stato sovrascritto nel suo registro, in tal modo i puntatori interni hanno bisogno di essere sottoposti a scansione.

Implicazioni[modifica | modifica sorgente]

Tracing garbage collection richiedono talvolta overhead impliciti che possono essere indipendenti dalla volontà del programmatore, e può a volte portare a problemi di prestazioni. Per esempio stop-the-world garbage collection durante le pause di esecuzione del programma, effettuano arbitrariamente raccolta di rifiuti, ciò è inadeguato per alcuni sistemi embedded ad alte prestazioni, per server e altre applicazioni con esigenze realtime. Le differenze principali tra allocazioni manuale e automatiche consistono in:

Allocazione heap manuale:

  • Ricerca di blocchi di dimensioni sufficienti secondo il best/first-fit
  • Manutenzione free list

Allocazione Garbage collection

  • Individuare gli oggetti raggiungibili
  • Copiare gli oggetti che sono stati spostati
  • Lettura/scrittura delle barriere
  • Ricerca di best/ first-block

È difficile stabilire quale dei due casi sia migliore in quanto il loro comportamento dipende dalla situazione. Alcuni progressi nel GC possono essere intesi come una migliore reazione a problemi di prestazioni. I primi sono stati GC di tipo stop-the-world ma le loro prestazioni sono state sviate in applicazioni interattive. Tecniche di Generational collection sono utilizzati sia con stop-the-world che incremental collection per aumentarne le prestazioni.

Determinismo[modifica | modifica sorgente]

Il Tracing garbage collection non è deterministico. Un oggetto che diventa ammissibile per il GC sarà generalmente eliminato alla fine, ma non vi è alcuna garanzia di quando e se ciò accadrà. Questo può portare problemi:

  • La maggior parte degli ambienti con l'analisi GC richiedono deallocazione manuale per non limitate risorse di memoria, che vengono eseguite in tempi non adatti.
  • L'impatto sulle prestazioni causate dal GC è apparentemente casuale e difficile da prevedere.

Reference counting[modifica | modifica sorgente]

Il Reference counting (conteggio dei riferimenti) è una forma di gestione automatica della memoria, dove ogni oggetto ha un conteggio del numero di riferimenti ad esso. Il contatore è incrementato quando viene creato un riferimento ad esso e diminuisce quando un riferimento viene distrutto. La memoria dell'oggetto viene recuperata quando il conteggio si azzera.

Ci sono due principali svantaggi per il conteggio dei riferimenti:

  • Se due o più oggetti rimandano l'uno all'altro, possono creare un ciclo in cui non vengono mai rilasciati ed il loro riferimento viene valutato zero. Alcuni sistemi di GC (come quello in CPython utilizzano uno specifico conteggio dei riferimenti per affrontare questo problema.[5]
  • Nelle implementazioni più semplici, ogni assegnazione di riferimento ed ogni riferimento perso richiedono spesso modifiche di uno o più contatori di riferimento. Quando viene utilizzato in un ambiente multithreading tali modifiche (di incremento/decremento) possono essere intrecciate, ma tale operazione risulta costosa per processi senza operazioni atomiche, come Compare-and-swap.

Un importante vantaggio del contatore dei riferimenti è che esso fornisce un GC deterministico.

Escape Analisys[modifica | modifica sorgente]

La Escape Analisys può essere utilizzata per spostare le locazioni di memoria dallo heap allo stack o ai registri della CPU, riducendo così la quantità di lavoro che deve essere svolta dal garbage collector. Lo spostamento è lecito quando il riferimento all'oggetto non sopravvive alla subroutine in cui è stato dichiarato, cioè quando il riferimento è a tutti gli effetti una variabile locale, che non viene passata ad ulteriori subroutine o ritornata a monte.

Esempio (Java)[modifica | modifica sorgente]

class A {
  final int finalValue;
 
  public A( B b ) {
    super();
    b.doSomething( this ); // this escapes!
    finalValue = 23;
  }
 
  int getTheValue() {
    return finalValue;
  }
}
 
class B {
  void doSomething( A a ) {
    System.out.println( a.getTheValue() );
  }
}

In questo esempio il costruttore della classe A passa la nuova istanza di A a B.doSomething, quindi il compilatore non può garantire che il puntatore non sopravviva al costruttore: il puntatore "escapes", fugge.

Disponibilità[modifica | modifica sorgente]

In generale, linguaggi di programmazione ad alto livello dispongono solitamente del GC come caratteristica standard. In linguaggi che non hanno il GC incorporato, spesso questo viene aggiunto tramite una libreria, come con il Garbage Collection Boehm del C e C++. La maggior parte dei linguaggi di programmazione funzionali come la ML, Haskell e APL hanno il GC come caratteristica di default. Il Lisp è stato il primo linguaggio funzionale che ha introdotto questo meccanismo.

Altri linguaggi dinamici come Ruby tendono ad usare il GC. I linguaggi di programmazione orientati agli oggetti, come Smalltalk, Java e ECMAScript, solitamente prevedono il GC integrato. Storicamente i linguaggi destinati ai principianti come BASIC utilitizzano spesso variabili di diversa lunghezza come stringhe e liste, in modo da sollevare il programmatore dall'onere di gestire manualmente la memoria. Il problema relativo alla velocità del sistema rallentato dall'azione del GC aumenta notevolmente nei microcomputer.

Ambienti limitati[modifica | modifica sorgente]

Il GC è raramente usato in ambienti di tipo embedded o real-time a causa dell'esigenze di tali ambienti. Tuttavia, sono stati sviluppati GC compatibili per questi ambienti limitati[6]. Microsoft.NET Micro Framework e Java Platform, Micro Edition sono piattaforme di software embedded che dispongono di Garbage collection.

Note[modifica | modifica sorgente]

  1. ^ Recursive functions of symbolic expressions and their computation by machine, Portal.acm.org. URL consultato il 29 marzo 2009.
  2. ^ Recursive functions of symbolic expressions and their computation by machine, Part I. URL consultato il 29 maggio 2009.
  3. ^ Maebe Jonas, Ronsse Michiel, De Bosschere Koen, Precise detection of memory leaks. URL consultato il 13 maggio 2010.
  4. ^ Copying and Pinning [collegamento interrotto]
  5. ^ Reference Counts in Extending and Embedding the Python Interpreter, 21 febbraio 2008. URL consultato il 13 novembre 2008.
    «While Python uses the traditional reference counting implementation, it also offers a cycle detector that works to detect reference cycles.».
  6. ^ Wei Fu and Carl Hauser, "A Real-Time Garbage Collection Framework for Embedded Systems". ACM SCOPES '05, 2005. http://portal.acm.org/ft_gateway.cfm?id=1140392&type=pdf&coll=GUIDE&dl=GUIDE&CFID=15151515&CFTOKEN=6184618

Voci correlate[modifica | modifica sorgente]