Comprensione e prevenzione delle perdite di memoria

Il supporto di Delphi per la programmazione orientata agli oggetti è ricco e potente. Classi e oggetti consentono la programmazione di codici modulari. Insieme a componenti più modulari e più complessi nascono bug più sofisticati e più complessi.

Mentre sviluppare applicazioni in Delphi è (quasi) sempre divertente, ci sono situazioni in cui ti senti come se il mondo intero fosse contro di te.

Ogni volta che è necessario utilizzare (creare) un oggetto in Delphi, è necessario liberare la memoria consumata (una volta non più necessaria). Sicuramente, i blocchi try / finally memory guarding possono aiutarti a prevenire perdite di memoria; spetta ancora a te salvaguardare il tuo codice.

Si verifica una perdita di memoria (o risorsa) quando il programma perde la capacità di liberare la memoria che consuma. Perdite di memoria ripetute fanno sì che l'utilizzo della memoria di un processo cresca senza limiti. Le perdite di memoria sono un problema serio: se si dispone di un codice che causa perdite di memoria, in un'applicazione in esecuzione 24 ore su 24, 7 giorni su 7, l'applicazione consumerà tutta la memoria disponibile e alla fine la macchina smetterà di rispondere.

Perdite di memoria in Delfi

Il primo passo per evitare perdite di memoria è capire come si verificano. Quella che segue è una discussione su alcune insidie ​​e le migliori pratiche comuni per la scrittura di codice Delphi senza perdite.

Nella maggior parte delle (semplici) applicazioni Delphi, in cui si utilizzano i componenti (pulsanti, promemoria, modifiche, ecc.) Rilasciati su un modulo (in fase di progettazione), non è necessario preoccuparsi troppo della gestione della memoria. Una volta che il componente viene inserito in un modulo, il modulo diventa il suo proprietario e libera la memoria acquisita dal componente una volta che il modulo è stato chiuso (distrutto). Il modulo, in quanto proprietario, è responsabile della deallocazione della memoria dei componenti ospitati. In breve: i componenti di un modulo vengono creati e distrutti automaticamente

Esempi di perdite di memoria

In qualsiasi applicazione Delphi non banale, sarà necessario creare un'istanza dei componenti Delphi in fase di esecuzione. Avrai anche alcune delle tue lezioni personalizzate. Supponiamo che tu abbia un TDeveloper di classe che ha un metodo DoProgram. Ora, quando è necessario utilizzare la classe TDeveloper, si crea un'istanza della classe chiamando il Creare metodo (costruttore). Il metodo Create alloca la memoria per un nuovo oggetto e restituisce un riferimento all'oggetto.

var
zarko: TDeveloper
inizio
zarko: = TMyObject.Create;
zarko.DoProgram;
fine;

Ed ecco una semplice perdita di memoria!

Ogni volta che crei un oggetto, devi eliminare la memoria che ha occupato. Per liberare la memoria di un oggetto allocato, è necessario chiamare il Gratuito metodo. Per essere assolutamente sicuri, dovresti anche usare il blocco try / finally:

var
zarko: TDeveloper
inizio
zarko: = TMyObject.Create;
provare
zarko.DoProgram;
infine
zarko.Free;
fine;
fine;

Questo è un esempio di allocazione di memoria sicura e codice di deallocazione.

Alcune parole di avvertimento: se si desidera creare un'istanza dinamica di un componente Delphi e liberarlo esplicitamente qualche tempo dopo, passare sempre zero come proprietario. In caso contrario, si possono presentare rischi inutili, nonché problemi di manutenzione del codice e delle prestazioni.

Oltre a creare e distruggere oggetti usando i metodi Crea e Libera, devi anche fare molta attenzione quando usi risorse "esterne" (file, database, ecc.).
Diciamo che devi operare su alcuni file di testo. In uno scenario molto semplice, in cui il metodo AssignFile viene utilizzato per associare un file su un disco a una variabile di file al termine del file, è necessario chiamare CloseFile per liberare l'handle del file per iniziare a utilizzarlo. Qui non hai una chiamata esplicita a "Gratis".

var
F: TextFile;
S: stringa;
inizio
AssignFile (F, 'c: \ somefile.txt');
provare
Readln (F, S);
infine
CloseFile (F);
fine;
fine;

Un altro esempio include il caricamento di DLL esterne dal codice. Ogni volta che usi LoadLibrary, devi chiamare FreeLibrary:

var
dllHandle: THandle;
inizio
dllHandle: = Loadlibrary ('MyLibrary.DLL');
// fa qualcosa con questa DLL
se dllHandle 0 quindi FreeLibrary (dllHandle);
fine;

Perdite di memoria in .NET?

Sebbene con Delphi per .NET Garbage Collector (GC) gestisca la maggior parte delle attività di memoria, è possibile avere perdite di memoria nelle applicazioni .NET. Ecco un articolo di discussione GC in Delphi per .NET.

Come combattere le perdite di memoria

Oltre a scrivere codice modulare sicuro per la memoria, è possibile prevenire perdite di memoria utilizzando alcuni degli strumenti di terze parti disponibili. Gli strumenti di correzione delle perdite di memoria di Delphi consentono di rilevare errori dell'applicazione Delphi come corruzione della memoria, perdite di memoria, errori di allocazione della memoria, errori di inizializzazione delle variabili, conflitti di definizione delle variabili, errori del puntatore e altro.