2009-10-06 4 views
8

Molto di quello che ho imparato su VB ho imparato dall'uso dell'analisi del codice statico (in particolare l'analizzatore di progetto di Aivosto). E una delle cose che controlla è se hai eliminato tutti gli oggetti e gli array. Lo facevo solo alla cieca perché l'ha detto la PA. Ma ora che conosco un po 'di più sul modo in cui VB rilascia risorse, mi sembra che queste cose dovrebbero accadere automaticamente. Si tratta di una funzione legacy del pre VB6, o esiste una ragione per cui è necessario impostare esplicitamente gli oggetti su null e utilizzare Erase sugli array?La cancellazione oggetto/deallazione array è davvero necessaria in VB6/VBA (Pro/Contro?)

risposta

4

Il problema, a quanto ho capito, ha a che fare con il fatto che VB6 (ei suoi predecessori) ha le sue radici in COM e nel suo sistema di raccolta dei rifiuti.

Immaginate, per esempio, di dichiarare un refernece a un oggetto da una libreria di terze parti. Quell'oggetto ha un conteggio di riferimento COM che viene utilizzato sia per mantenerlo in vita che per determinare quando deve essere distrutto. Non viene distrutto quando lo si imposta su Nothing, ma quando il conteggio dei riferimenti dell'oggetto raggiunge lo zero.

Ora, non tutti i componenti COM sono stati scritti in Visual Basic. Alcuni sono stati scritti in C o C++. La gestione strutturata delle eccezioni non esisteva in tutte le lingue. Quindi, se si è verificato un errore, il conteggio dei riferimenti sull'oggetto non è stato garantito in modo da ridurlo correttamente e gli oggetti COM erano noti per rimanere in attesa più a lungo di quanto previsto. Questo non era un problema con Visual Basic, di per sé. Era un problema di COM. (E questo, si potrebbe notare, è perché .NET non usa il conteggio dei riferimenti.)

Ecco perché gli sviluppatori di Visual Basic sono diventati ossessivi sul rilascio dei riferimenti agli oggetti prima di uscire dalle routine. Semplicemente non sai che cosa un componente che stai allocando sta creando sotto il cofano. Ma quando rilasci il tuo riferimento ad esso, stai almeno rilasciando il tuo conteggio dei riferimenti ad esso. È diventato quasi un mantra religioso. Dichiara, usa, rilascia. Era il modo COM di fare le cose.

Certo, Visual Basic potrebbe essere migliore o più veloce alle variabili di dereferenziamento che ho dichiarato sullo stack. Ma dannazione, voglio che sia OBVIOUS che quegli oggetti siano stati rilasciati. Un po 'di sicurezza va molto lontano quando stai cercando di rintracciare una perdita di memoria.

0

Lo faccio sempre per le buone pratiche, non si sa mai cosa potrebbe fare un'eccezione se si cade in una e i propri oggetti non vengono deallocati. Dovresti ricollocarli nelle dichiarazioni finali e accertarti che non stiano utilizzando alcuna memoria altrimenti potresti incappare in una perdita di memoria.

Avevo un problema all'interno di un semplice sistema time-tracker in cui il server continuava a bloccarsi in modo casuale, ci sono volute settimane per determinare che si trattava di una perdita di memoria di un oggetto che avrebbe dovuto autodistruggersi da solo. Il mio codice è stato gettato in un'eccezione e non è mai stato ripulito dopo aver causato l'arresto del server (il vero sito Web non dell'intero server).

+0

Interessante, potrebbe chiedere che tipo di oggetto era? Qual era il suo scopo? È stata lanciata un'eccezione intercettabile o l'app si è bloccata? Quando viene lanciata un'eccezione standard, la procedura viene chiusa. Anche se, per eccezione, tutti i riferimenti locali sono ancora automaticamente distrutti. Quindi se non ci fossero riferimenti all'oggetto al di fuori della procedura, cosa stava causando l'oggetto a rimanere "vivo"? – Oorang

+2

Non ci sono blocchi Try/Catch/Finally o Exceptions in VB6/VBA. – HardCode

+0

Non ci sono blocchi Try/Catch/Finally, ma ci sono eccezioni intercettabili. Dai un'occhiata a Err.Raise. – Oorang

-2

Sì, imposta tutti gli oggetti su Niente e ripulisci il più possibile. VB6 è noto per avere perdite di memoria quando non si pulisce il tuo materiale. La raccolta dei dati inutili è stata sottopagata in VB6/VBA.

+0

Hi HardCode, ho sentito spesso esprimere questo sentimento. Quello che sto cercando è un esempio concreto/riproducibile? – Oorang

+0

Non c'è niente di sbagliato nel meccanismo di garbage collection di VB6. Sono altri componenti che non rilasciano correttamente riferimenti o che richiedono una semantica di smistamento molto specifica che la rompa. Non è colpa di VB6 che ci siano componenti scritti male che non rispettano le regole. –

+4

A volte è necessario abbattere esplicitamente anche elementi come riferimenti ad oggetti circolari. In generale scope-exit rilascerà refences locali e deallocate gli array, ma in un ambito di lunga durata come i dati globali del modulo, si consiglia di eseguire una pulizia tattica tempestiva solo per liberare risorse di memoria. Il punto è proprio non è una regola generale. È necessario essere consapevoli di ciò che si sta facendo e quando c'è valore nella deallocazione iniziale. – Bob77

13

Matt Curland, autore di Advanced Visual Basic 6, che conosce meglio Visual Basic di quanto lo sarà la maggior parte di noi, pensa che sia uno sforzo inutile. Prendi in considerazione questa citazione (p110) su DAO, la libreria di accesso ai dati COM che si rivolge principalmente al motore di database di Access:

un altro esempio di codice di cancellazione insufficiente. DAO ha metodi Close che devono essere chiamati nell'ordine corretto e gli oggetti devono essere rilasciati nell'ordine corretto (Recordset prima del database, ad esempio). Questo comportamento del modello di oggetto singolo povero ha malinteso che VB perde la memoria a meno che non si impostino esplicitamente tutte le variabili locali su alla fine di una funzione . Questa è una nozione completamente falsa in un modello di oggetto ben progettato . VB può cancellare le variabili più velocemente alla fine della linea Sub line che puoi dal codice, e controlla le variabili anche se tu rilascia esplicitamente i tuoi riferimenti. Qualsiasi tentativo effettuato è duplicato.

+0

Ciao ODW, Questo è in linea con la mia linea di pensiero. DAO è l'unico oggetto che sapevo di sicuro doveva essere rilasciato correttamente (al di fuori di Win32). Sei a conoscenza di altri "casi speciali"? – Oorang

2

Hai letto questo Aivosto web page (dai creatori di Project Analyzer)?

Se si utilizza variabili statiche, è importante recuperare la memoria hanno occupato quando non è necessario le variabili più. Con la variabile dinamica la memoria non è tanto un problema di , perché sono distrutti quando la procedura termina.

In altre parole, non è necessario preoccuparsi di cancellare variabili locali ordinarie, non statiche.

+0

+1 Per aver notato che :) Anche se è un giorno piuttosto raro quando sto usando la statica. Di solito uso solo variabili a livello di modulo privato se ho bisogno di qualcosa di ricordato. – Oorang