|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jan 2009
Messaggi: 609
|
[C#] Problema di memory leak
Ciao a tutti.
Mi sono accorto di un fastidioso problema di memory leak in C# che non riesco davvero a risolvere. Mi spiego: ho un form1 con un semplice pulsante che non fa altro che aprire un altro form2 . Quando chiudo poi questo form2 e lo riapro con lo stesso pulsante del form1, noto dal task manager che la memoria occupata dal mio programma cresce senza limiti ogni qualvolta ripeto questa operazione. Giusto per rendervi l'idea, se all'apertura l'applicazione occupa circa 3.5MB, se apro e chiudo il form2 per una decina di volte, l'occupazione cresce a 8MB, nonostante io provveda a chiudere la finestra - con il metodo Close() - e non a nasconderla con Hide(). Non so se mi sono spiegato bene... P.S: ho provato anche a liberare le risorse con Dispose() ma non ho risolto assolutamente niente. Grazie a chi mi vorrà dare un aiuto.
__________________
L'iPad? Potrebbe esserci gente che, pur d'avere il nuovo gadget, si mette a leggere i libri. Questa sì sarebbe una rivoluzione (Beppe Severgnini)
|
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Aug 2003
Città: Rimini
Messaggi: 422
|
Quote:
Attenzione però, la dispose, non implica le deallocazione istantanea dell'oggetto, ma "marca" l'oggetto come deallocabile. Ci pensa piu il garbage colletor di .Net a liberare la memoria, quando lo ritiene piu opportuno... |
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Dovresti postare un esempio di codice che verifica il tuo problema.
Se ci sono apparenti memory leak è perchè mantieni qualche riferimento appeso da qualche parte per cui il GC non interviene. Oppure il GC non interviene nonostante che il tuo codice sia corretto perchè non ritiene che sia necessario, ma è decisamente l'opzione meno probabile. |
|
|
|
|
|
#4 | ||
|
Senior Member
Iscritto dal: Jan 2009
Messaggi: 609
|
Quote:
Quote:
Allego al post un esempio: un'applicazione banale con due form. Provate ad aprire la finestra Form2 dal pulsante del Form1, poi chiudete la finestra Form2 e ripetete l'operazione. Dal task manager si vede che l'occupazione di memoria dell'applicazione cresce ogni volta. Non credo sia normale un comportamento del genere. Qui il codice: Form1: Codice:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 Window = new Form2();
Window.Show();
}
}
Codice:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.Dispose();
this.Close();
}
}
P.S: in questo esempio la memoria cresce lentamente perché si tratta di due stupidi form senza alcun controllo, ma vi assicuro che se si tratta di una finestra piena di controlli, l'occupazione di memoria cresce in modo considerevole.
__________________
L'iPad? Potrebbe esserci gente che, pur d'avere il nuovo gadget, si mette a leggere i libri. Questa sì sarebbe una rivoluzione (Beppe Severgnini)
|
||
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Jan 2009
Messaggi: 609
|
up
![]() Ah, tra l'altro mi sono accorto anche che dopo aver richiamato il metodo "Close", l'oggetto Form2 viene effettivamente distrutto, tant'è che se provo a richiamarlo, mi viene sollevata un'eccezione di NullObjectReference (o qualcosa del genere). Ma allora come mai non viene liberata la memoria dal GC?
__________________
L'iPad? Potrebbe esserci gente che, pur d'avere il nuovo gadget, si mette a leggere i libri. Questa sì sarebbe una rivoluzione (Beppe Severgnini)
Ultima modifica di alex783 : 27-04-2009 alle 09:43. |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Dec 2003
Messaggi: 4907
|
Provato con GC.Collect()?
|
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Quote:
.Dispose() non forza l'eliminazione dell'oggetto e il rilascio della memoria occupata nello stesso preciso istante in cui viene invocato, ma piuttosto "marca" l'oggetto in questione per il prossimo passaggio di GC. In soldoni, senza stare a fare grandi discorsi sui massimi sistemi, direi che il comportamento "anomalo" riscontrato nella gestione della memoria in .Net, è dovuto principalmente a 2 fattori : 1. Il GC ha dei tempi "tutti suoi", spesso imperscrutabili. Bisogna lasciarlo fare. Tu dici che aprendo N Form2 da Form1 la memoria cresce continuamente, ma non è corretto. In effetti GC interviene ( nel suo solito modo "pigro", ma credo sia volutamente così ). Se ad esempio apri 10 Form2, poi chiudi la decima, non notando alcun decremento di uso della Ram, poi magari riapri una decima Form2 e stranamente la memoria occupata diminuisce... GC.Collect() a mio parere non è una buona idea : anzitutto nella maggior parte dei casi non noterai alcuna ottimizzazione della Ram, secondariamente può essere anche "pericoloso" ( su molti Forum, anche su MSDN, spesso e volentieri ne viene sconsigliato l'uso )... 2. Non dimentichiamo che lo stesso Windows gioca un ruolo importante e che "storicamente" l'ottimizzazione della Ram non è mai stata un cavallo di battaglia. Perciò la colpa di tutto ciò si distribuisce nella catena Applicazione-FrameWork-Windows... Possibile soluzione : tempo fa ho avuto il tuo stesso problema e l'ho risolto creandomi una piccola classe static con qualche metodo di gestione della Ram, prova questo ( dovrebbe dare una bella scrollatina alla memoria... ) : Codice:
public static void OttimizzaMemoria()
{
System.Diagnostics.Process CP = System.Diagnostics.Process.GetCurrentProcess();
try
{
CP.MaxWorkingSet = (IntPtr)((int)CP.MaxWorkingSet - 1);
}
catch (System.Exception)
{
//...
}
}
|
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Sicuro che sia DAVVERO un memory leak? Mi sembra un po' presto per dirlo.
Prova a fare dei test piu' lunghi. Tutto sommato 8Mb sono ancora pochi, magari gc non si e' ancora deciso ad intervenire
__________________
In God we trust; all others bring data |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Dec 2003
Messaggi: 4907
|
Quote:
|
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Jan 2009
Messaggi: 609
|
Quote:
Grazie mille!
__________________
L'iPad? Potrebbe esserci gente che, pur d'avere il nuovo gadget, si mette a leggere i libri. Questa sì sarebbe una rivoluzione (Beppe Severgnini)
|
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Feb 2003
Città: Stockholm (SE)
Messaggi: 1343
|
mi spiegheresti cosa fa quella chiamata?
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Jan 2009
Messaggi: 609
|
Ho trovato questo su MSDN: http://msdn.microsoft.com/it-it/libr...et(VS.80).aspx
__________________
L'iPad? Potrebbe esserci gente che, pur d'avere il nuovo gadget, si mette a leggere i libri. Questa sì sarebbe una rivoluzione (Beppe Severgnini)
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Non è una mossa intelligente ridurre lo spazio di memoria dell'applicativo.
Se si vuole il controllo completo della memoria è bene cambiare linguaggio. Altrimenti si prendono gli aspetti positivi del .NET trascurando gli inconvenienti (se questi costituiscono effettivamente un problema) |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Sep 2006
Messaggi: 475
|
Si vede che non hai ancora visto all'opera i componenti Timer... quelli si che ciucciano memoria se non stati attento!
Comunque non preoccuparti più di tanto perché in ogni caso non puoi cambiare la situazione. dot net comunque ha un sistema per il garbage collection che esegue automaticamente al verificarsi di determinate condizioni.
__________________
Fisso: Case Chieftec BA01BBB - Corsair TX-750W - ASUS P5N-E SLI - Intel Core Duo E8400 Cooled by Cooler Master V8 - 4Gb RAM (4x1GB) 800 Corsair XMS2 - ASUS EN8800GTS 512MB - 2xHD Hitachi 160gb in Raid 0 & 1HD Hitachi 320gb - Monitor LG L1919S - Tastiera&Mouse Logitech G11 & MX-518 - Volante Logitech Wingman Formula EX + Atomic Drive&Station |
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Quote:
|
|
|
|
|
|
|
#17 |
|
Member
Iscritto dal: Jul 2008
Messaggi: 237
|
Piuttosto che andare a pasticciare con il working set, che in caso può anche causare rallentamenti notevoli ed altri problemi se impostato male, forse vale la pena di forzare la collection di oggetti di generazioni più recenti da parte del GC..!
|
|
|
|
|
|
#18 | |
|
Senior Member
Iscritto dal: Jan 2009
Messaggi: 609
|
Quote:
Purtroppo era un problema a cui tenevo molto risolvere, perché la mia applicazione deve restare caricata nella traybar, e non voglio che occupi 20MB, se non di più, anche quando non fa nulla. Ora, invece, occupa sì 20 MB quando esegue i task, ma appena finisce, scende ad appena 1.5 MB
__________________
L'iPad? Potrebbe esserci gente che, pur d'avere il nuovo gadget, si mette a leggere i libri. Questa sì sarebbe una rivoluzione (Beppe Severgnini)
|
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Lascia tutto com'e'. Quando il sistema avra' bisogno di memoria, oppure quando il sistema non sara' particolarmente sotto stress, Il Garbage Collector passera' da solo e liberera' la memoria per altri processi.
La memoria resta in questo momento allocata per futuri usi. Poiche' allocare memoria costa tempo, la scelta e' quella di tenerla allocata fino a che non serve effettivamente per altro, sperando in un futuro riuso dello spazio gia' allocato dal Framework. Il fatto che forzare GC.Collect() liberi la memoria e' segno che non c'e' alcun Memory Leak, in presenza dei quali il Garbage Collector non potrebbe fare molto.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
#20 | |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Quote:
Certo non consiglio di farlo in un Timer, o ad ogni click di un pulsante, ovvio. Sempre usare buon senso. 2. Beh, fatti un giretto su MSDN e molti altri Forum di Programmazione, e non troverai poi molta gente che consiglia di forzare GC. |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 15:14.












Grazie mille!








