strategie per tenere sotto controllo le perdite di memoria in linguaggi non gestiti da memoria

3

Quando si parla di linguaggi gestiti da memoria diversa come C, C ++ o Fortran (il mio caso), diventa sempre più difficile tenere traccia dell'allocazione / deallocazione della memoria, specialmente quando la proprietà deve essere condivisa. Ho implementato il refcounting per i miei oggetti, ma questo lo rende ancora più complicato in quanto non c'è posto dove un oggetto viene deallocato. Ogni decremento di riferimento è un potenziale punto di deallocation.

Quindi ora è sempre più difficile per me rintracciare le perdite di memoria. Mi stavo chiedendo alcune tecniche consolidate per gestire la gestione della memoria in linguaggi gestiti senza memoria, a parte il valgrinding.

Modifica: sono più interessato alle strategie di programmazione attive (che sono generali).

    
posta Stefano Borini 06.08.2012 - 15:13
fonte

4 risposte

5

Li hai già coperti.

Se la proprietà condivisa causa problemi di gestione della memoria, sposta il tuo progetto lontano dalla proprietà condivisa. Di solito ciò comporta la designazione di una parte del codice come proprietario e quindi responsabile della deallocazione. Puntatori deboli (o l'equivalente) possono aiutare questo a livello di programmazione. RAII può essere applicato più liberamente quando esiste una proprietà singola.

Se hai un rimborso (o un altro meccanismo per l'auto-deallocazione), non ti interessa se / dove si trova la deallocazione. È sufficiente testare / provare che la struttura distribuirà correttamente la memoria quando è prevista.


Alcune altre cose su cui concentrarsi:

  • I pattern di gestione della memoria piacciono. Quando il tuo codice segue pattern coerenti, avrà un comportamento coerente per quanto riguarda la gestione della memoria. Quando fai rileva perdite di memoria, puoi concentrarti sui casi eccezionali, rendendoli più facili da trovare.
  • Riduci il tuo ambito. se gli oggetti vivono solo in un ambito isolato, è più facile ragionare sulla proprietà e sulla loro durata.
  • Assegna solo ciò di cui hai bisogno. Meglio dei piccoli ambiti non ha scopo. Se non è necessario allocare memoria (entro limiti ragionevoli), non farlo.
risposta data 06.08.2012 - 15:44
fonte
4

Gli strumenti sono importanti

Ci sono diversi strumenti che possono aiutarti. Personalmente stavo usando Visual Leak Detector 2 anni fa, sebbene possa causare ritardi di grandi dimensioni in caso di perdita di grandi blocchi (mostra il contenuto del intero blocco trapelato).

Se non vuoi ricompilare (come richiede Visual Leak Detector) ti consiglio WinDbg , che è sia potente che veloce (anche se non è così facile da usare come si potrebbe desiderare).

Ecco alcuni riferimenti su perdite di memoria e gestione della memoria in generale:

Standard e schemi di codifica

Oltre agli strumenti, consiglierei di lavorare su coding standards and patterns e sulla revisione tra pari del codice tra gli sviluppatori del progetto. Ciò può aiutare a sfruttare un approccio comune nei problemi di risoluzione dei problemi di perdita di memoria.

    
risposta data 06.08.2012 - 15:15
fonte
2

Le perdite di memoria non sono un problema una volta capito come funziona la gestione della memoria. Per affrontarli, hai bisogno di due cose:

Per prima cosa, ottieni un gestore di memoria di debug. Non so cosa sia disponibile per C, C ++ o Fortran, dal momento che sono uno sviluppatore Delphi, ma in Delphi c'è una sostituzione del gestore di memoria chiamata FastMM FullDebugMode che terrà traccia delle allocazioni e delle allocazioni e ti avviserà alla fine di il programma se hai perso qualcosa. Fornisce una traccia dello stack, informazioni sul tipo e altre utili informazioni di debug per ogni perdita, il che rende molto semplice rintracciare e correggere. Dovresti avere qualcosa di simile disponibile per altre lingue.

In secondo luogo, è necessario capire come strutturare l'allocazione della memoria per evitare che si verifichino perdite. La tecnica per questo può essere formalmente indicata come Principio di proprietà singola :

Each variable in your code has one and only one owner, and it’s the responsibility of that owner to free the variable’s memory when it is no longer needed.

Quello che è il singolo proprietario varierà a seconda di cosa sono le variabili e per cosa sono utilizzate. I primitivi, ad esempio, appartengono allo stack e verranno automaticamente ripuliti al ritorno di una funzione. La maggior parte degli oggetti, al contrario, appartiene a un altro oggetto. Quelle che non lo sono sono generalmente variabili locali che dovrebbero essere ripulite dalla routine che le ha create prima che esca.

Gli oggetti condivisi da più altri oggetti non hanno più proprietari; se ci pensi in questo modo stai cercando dei problemi. Invece, dovrebbero avere un unico proprietario, un sistema di conteggio dei riferimenti o un oggetto principale che sapete sarà più lungo di tutti gli altri.

Quando si interiorizza il Principio di proprietà singola, si scriverà molto meno codice con perdite. E quando hai un gestore di memoria di debug per fare rapporto su ciò che hai perso, correggere i pochi errori che farai non farai più una prospettiva spaventosa.

    
risposta data 06.08.2012 - 16:42
fonte
0

Uso il mio set di routine wrapper per l'allocazione e la deallocazione, che richiedono che ciascun blocco sia identificato da una stringa che identifica l'allocazione. Per esempio  myAlloc (size, "temporary for mumble sort")

In modalità di debug, ogni blocco viene aggiunto a un hashtable (potenzialmente grande) e all'uscita le perdite rimanenti vengono segnalate insieme alle stringhe per il cestino. In modalità nondebug, viene eseguita solo la contabilità riepilogativa.

Da questo schema, ottengo un tripwire nel codice di produzione che avverte di perdite impreviste e ricevo un feedback dettagliato e immediato quando si sviluppa su ciò che sta perdendo.

    
risposta data 06.08.2012 - 21:26
fonte

Leggi altre domande sui tag