Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Deep Tech Revolution: così Area Science Park apre i laboratori alle startup
Deep Tech Revolution: così Area Science Park apre i laboratori alle startup
Siamo tornati nel parco tecnologico di Trieste per il kick-off del programma che mette a disposizione di cinque startup le infrastrutture di ricerca, dal sincrotrone Elettra ai laboratori di genomica e HPC. Roberto Pillon racconta il modello e la visione
HP OMEN MAX 16 con RTX 5080: potenza da desktop replacement a prezzo competitivo
HP OMEN MAX 16 con RTX 5080: potenza da desktop replacement a prezzo competitivo
HP OMEN MAX 16-ak0001nl combina RTX 5080 Laptop e Ryzen AI 9 HX 375 in un desktop replacement potente e ben raffreddato, con display 240 Hz e dotazione completa. Autonomia limitata e calibrazione non perfetta frenano l'entusiasmo, ma a 2.609 euro è tra le proposte più interessanti della categoria.
Recensione Google Pixel 10a, si migliora poco ma è sempre un'ottima scelta
Recensione Google Pixel 10a, si migliora poco ma è sempre un'ottima scelta
Google ha appena rinnovato la sua celebre serie A con il Pixel 10a, lo smartphone della serie più conveniente se consideriamo il rapporto tra costo e prestazioni. Con il chip Tensor G4, un design raffinato soprattutto sul retro e l'integrazione profonda di Gemini, il colosso di Mountain View promette un'esperienza premium a un prezzo accessibile. E il retro non ha nessuno scalino
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 26-04-2009, 11:04   #1
alex783
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)
alex783 è offline   Rispondi citando il messaggio o parte di esso
Old 26-04-2009, 14:49   #2
supertonno
Senior Member
 
L'Avatar di supertonno
 
Iscritto dal: Aug 2003
Città: Rimini
Messaggi: 422
Quote:
Originariamente inviato da alex783 Guarda i messaggi
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.
In teoria fatta la Dispose() dovresti essere a posto.
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...
supertonno è offline   Rispondi citando il messaggio o parte di esso
Old 26-04-2009, 14:58   #3
tomminno
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.
tomminno è offline   Rispondi citando il messaggio o parte di esso
Old 26-04-2009, 15:31   #4
alex783
Senior Member
 
Iscritto dal: Jan 2009
Messaggi: 609
Quote:
Originariamente inviato da supertonno Guarda i messaggi
In teoria fatta la Dispose() dovresti essere a posto.
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...
Quote:
Originariamente inviato da tomminno Guarda i messaggi
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.
Allora... innanzittutto grazie per le vostre risposte...

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();
        }
    }
Form2:
Codice:
public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            
            this.Dispose();
            this.Close();
        }
    }
Come si può fare per risolvere questo problema?

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.

Allegati
File Type: zip WindowsFormsApplication1.zip (3.5 KB, 0 visite)
__________________
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)
alex783 è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 09:41   #5
alex783
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.
alex783 è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 09:45   #6
||ElChE||88
Senior Member
 
Iscritto dal: Dec 2003
Messaggi: 4907
Provato con GC.Collect()?
||ElChE||88 è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 10:47   #7
MarcoGG
Senior Member
 
L'Avatar di MarcoGG
 
Iscritto dal: Dec 2004
Messaggi: 3210
Quote:
Originariamente inviato da alex783 Guarda i messaggi
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?
Infatti. .Close() già da solo basterebbe a fare tutto.
.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) 
            {
                //...
            }
        }
Chiamalo semplicemente dopo il .Close() del Form2... e dimmi che effetto ti fa !
MarcoGG è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 10:49   #8
sottovento
Senior Member
 
L'Avatar di sottovento
 
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
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 10:51   #9
||ElChE||88
Senior Member
 
Iscritto dal: Dec 2003
Messaggi: 4907
Quote:
Originariamente inviato da MarcoGG Guarda i messaggi
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 )...
GC.Collect() è assoluatmente da evitare nel codice normale, ma in questo caso potrebbe indicare se il problema è del GC o del codice...
||ElChE||88 è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 14:03   #10
alex783
Senior Member
 
Iscritto dal: Jan 2009
Messaggi: 609
Quote:
Originariamente inviato da MarcoGG Guarda i messaggi
Infatti. .Close() già da solo basterebbe a fare tutto.
.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) 
            {
                //...
            }
        }
Chiamalo semplicemente dopo il .Close() del Form2... e dimmi che effetto ti fa !
Ehm... quando invoco questo metodo, la memoria occupata scende da 5MB a 1.5MB Ottimo!

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)
alex783 è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 18:43   #11
MarcoGG
Senior Member
 
L'Avatar di MarcoGG
 
Iscritto dal: Dec 2004
Messaggi: 3210
Quote:
Originariamente inviato da alex783 Guarda i messaggi
Ehm... quando invoco questo metodo, la memoria occupata scende da 5MB a 1.5MB Ottimo!

Grazie mille!
MarcoGG è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 19:18   #12
Kralizek
Senior Member
 
L'Avatar di Kralizek
 
Iscritto dal: Feb 2003
Città: Stockholm (SE)
Messaggi: 1343
mi spiegheresti cosa fa quella chiamata?
Kralizek è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 21:47   #13
alex783
Senior Member
 
Iscritto dal: Jan 2009
Messaggi: 609
Quote:
Originariamente inviato da Kralizek Guarda i messaggi
mi spiegheresti cosa fa quella chiamata?
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)
alex783 è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2009, 23:37   #14
tomminno
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)
tomminno è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2009, 09:08   #15
Steel Jans
Senior Member
 
L'Avatar di Steel Jans
 
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
Steel Jans è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2009, 11:50   #16
MarcoGG
Senior Member
 
L'Avatar di MarcoGG
 
Iscritto dal: Dec 2004
Messaggi: 3210
Quote:
Originariamente inviato da tomminno Guarda i messaggi
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)
Quindi la tua "mossa intelligente", a chi chiede come ottimizzare l'utilizzo di memoria sviluppando in C#, è consigliare... di cambiare linguaggio ?
MarcoGG è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2009, 12:31   #17
!k-0t1c!
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..!
!k-0t1c! è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2009, 12:42   #18
alex783
Senior Member
 
Iscritto dal: Jan 2009
Messaggi: 609
Quote:
Originariamente inviato da MarcoGG Guarda i messaggi
Quindi la tua "mossa intelligente", a chi chiede come ottimizzare l'utilizzo di memoria sviluppando in C#, è consigliare... di cambiare linguaggio ?
Il tuo metodo sta funzionando alla grande e per ora non sto riscontrando alcuna anomalia

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)
alex783 è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2009, 12:45   #19
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2009, 12:46   #20
MarcoGG
Senior Member
 
L'Avatar di MarcoGG
 
Iscritto dal: Dec 2004
Messaggi: 3210
Quote:
Originariamente inviato da !k-0t1c! Guarda i messaggi
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..!
1. Nessun pasticcio. Ho usato quel sistema in un'applicazione recentemente senza alcun problema. Se fosse così dannoso credo che, alla versione 2008 di C#, dovrebbe essere quantomeno deprecato.
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.
MarcoGG è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Deep Tech Revolution: così Area Science Park apre i laboratori alle startup Deep Tech Revolution: così Area Science P...
HP OMEN MAX 16 con RTX 5080: potenza da desktop replacement a prezzo competitivo HP OMEN MAX 16 con RTX 5080: potenza da desktop ...
Recensione Google Pixel 10a, si migliora poco ma è sempre un'ottima scelta Recensione Google Pixel 10a, si migliora poco ma...
6G, da rete che trasporta dati a rete intelligente: Qualcomm accelera al MWC 2026 6G, da rete che trasporta dati a rete intelligen...
CHUWI CoreBook Air alla prova: design premium, buona autonomia e qualche compromesso CHUWI CoreBook Air alla prova: design premium, b...
CL1: le prime installazioni di data cent...
Yoshi and the Mysterious Book: annunciat...
CATL frena sulle batterie a stato solido...
NIO, ecco il profitto nel quarto trimest...
iRobot Roomba Mini: il robot aspirapolve...
Manda le DDR5 in assistenza, il venditor...
Scope elettriche lavapavimenti di marca ...
Delle oltre 750.000 offerte solo il 2% &...
Tutti gli smartphone più convenie...
MG annuncia MG4X, SUV con batteria allo ...
Ritratti professionali su fascia media: ...
Il biatleta ucraino Maksym Murashkovskyi...
Smartwatch Amazfit e Offerte di Primaver...
Offerte di Primavera: 4 TV hanno prezzi ...
Volkswagen, il nuovo piano porta i licen...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 14:06.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v