Domanda

In uno dei miei moduli VB6, creo diversi altri oggetti modulo e li memorizzo in variabili membro.

Private m_frm1 as MyForm
Private m_frm2 as MyForm

// Later...
Set m_frm1 = New MyForm
Set m_frm2 = New MyForm

Noto che perdo memoria ogni volta che questo modulo (genitore) viene creato e distrutto.È necessario per me assegnare queste variabili membro a Nothing In Form_Unload()?

In generale, quando è obbligatorio?

RISOLTO:Questa particolare perdita di memoria è stata risolta quando ho eseguito un Unload sui moduli in questione, non quando imposto il modulo su Nothing.Sono riuscito a rimuovere alcune altre perdite di memoria impostando esplicitamente alcune istanze di Moduli di classe su Nothing, anche.

È stato utile?

Soluzione

@Matt Dillard - L'impostazione di questi valori su Nulla ha risolto la perdita di memoria?

VB6 non ha un garbage collector formale, più sulla falsariga di quanto detto da @Konrad Rudolph.

In realtà chiamare lo scaricamento sui moduli mi sembra essere il modo migliore per garantire che il modulo principale venga ripulito e che ogni sottomodulo ripulisca le proprie azioni.

L'ho testato con un progetto vuoto e due moduli vuoti.

Private Sub Form_Load()
  Dim frm As Form2
  Set frm = New Form2
  frm.Show
  Set frm = Nothing
End Sub

Dopo aver eseguito entrambi i moduli vengono lasciati visibili.partire dal nulla ha fatto bene...Niente.

Dopo aver impostato frm su nulla, l'unico handle aperto per questo modulo avviene tramite il riferimento.

Unload Forms(1)

Vedo correttamente il problema?

  • Josh

Altri suggerimenti

In realtà, VB6 implementa RAII proprio come C++, il che significa che i riferimenti dichiarati localmente vengono automaticamente impostati su Nothing alla fine di un blocco.Allo stesso modo, esso Dovrebbe reimposta automaticamente le variabili della classe membro dopo l'esecuzione Class_Terminate.Tuttavia, ci sono state diverse segnalazioni secondo cui ciò non viene fatto in modo affidabile.Non ricordo alcun test rigoroso, ma è sempre stata una buona pratica reimpostare manualmente le variabili dei membri.

@Martino

VB6 aveva un'istruzione "With/End With" che funzionava "come" l'istruzione Using() in C#.NET.E, naturalmente, meno cose globali hai, meglio è per te.

With/End With non funziona come l'istruzione Using, non "Dispose" alla fine dell'istruzione.

With/End With funziona in VB 6 proprio come in VB.Net, è fondamentalmente un modo per chiamare rapidamente le proprietà/metodi dell'oggetto.per esempio.

Con acustomer .firstName = "John" .LastName = "Smith" End con

Gli oggetti in VB hanno un conteggio dei riferimenti.Ciò significa che un oggetto conta quante altre variabili oggetto hanno un riferimento ad esso.Quando non sono presenti riferimenti all'oggetto, l'oggetto viene sottoposto a Garbage Collection (eventualmente).Questo processo fa parte della specifica COM.

Di solito, quando un oggetto istanziato localmente esce dall'ambito (ad es.esce dal sub), il suo conteggio dei riferimenti diminuisce di uno, in altre parole la variabile che fa riferimento all'oggetto viene distrutta.Quindi nella maggior parte dei casi non sarà necessario impostare esplicitamente un oggetto uguale a Nothing all'uscita da Sub.

In tutti gli altri casi è necessario impostare esplicitamente una variabile oggetto su Nothing, per diminuire il conteggio dei riferimenti (di uno).L'impostazione di una variabile oggetto su Nothing non distruggerà necessariamente l'oggetto, è necessario impostare TUTTI i riferimenti su Nothing.Questo problema può diventare particolarmente acuto con strutture dati ricorsive.

Un altro problema è quando si utilizza la parola chiave New in una dichiarazione di variabile oggetto.Un oggetto viene creato solo al primo utilizzo, non nel punto in cui viene utilizzata la parola chiave New.L'utilizzo della parola chiave New nella dichiarazione ricreerà l'oggetto al primo utilizzo ogni volta che il conteggio dei riferimenti arriva a zero.Quindi impostare un oggetto su Nothing potrebbe distruggerlo, ma l'oggetto verrà ricreato automaticamente se si fa nuovamente riferimento.Idealmente non dovresti dichiarare utilizzando la parola chiave New, ma utilizzando l'operatore New che non ha questo comportamento di resurrezione.

A rigor di termini mai, ma dà al netturbino un forte suggerimento per ripulire le cose.

Di regola: fallo ogni volta che hai finito con un oggetto che hai creato.

Impostando un riferimento VB6 su Nothing, diminuisce il numero di riferimenti che VB ha per quell'oggetto.Se e solo se il conteggio è zero, l'oggetto verrà distrutto.

Non pensare che solo perché imposti su Niente verrà "raccolta spazzatura" come in .NET

VB6 utilizza un contatore di riferimento.

Sei incoraggiato a impostare su "Nothing" oggetti istanziati che fanno riferimento al codice C/C++ e cose del genere.È passato molto tempo dall'ultima volta che ho toccato VB6, ma ricordo di aver impostato file e risorse su zero.

In entrambi i casi non farà male (se fosse già Niente), ma ciò non significa che l'oggetto verrà distrutto.

VB6 aveva un'istruzione "With/End With" che funzionava "come" l'istruzione Using() in C#.NET.E, naturalmente, meno cose globali hai, meglio è per te.

Ricordare che, in entrambi i casi, a volte creare un oggetto di grandi dimensioni è più costoso che mantenere vivo un riferimento e riutilizzarlo.

Ho avuto un problema simile a questo qualche tempo fa.Mi sembra che impedirebbe anche la chiusura dell'app, ma potrebbe essere applicabile qui.

Ho recuperato il vecchio codice e assomiglia a qualcosa del tipo:

Dim y As Long
For y = 0 To Forms.Count -1
    Unload Forms(x)
Next

Potrebbe essere più sicuro scaricare il file m_frm1.e non semplicemente impostarlo su nulla.

Un punto importante che non è stato ancora menzionato qui è che impostare un riferimento a un oggetto su Nothing farà funzionare il distruttore dell'oggetto (Class_Terminate se la classe è stata scritta in VB) se non ci sono altri riferimenti all'oggetto (il conteggio dei riferimenti è zero ).

In alcuni casi, soprattutto quando si utilizza un modello RAII, il codice di terminazione può eseguire codice che può generare un errore.Credo che questo sia il caso di alcune classi ADODB.Un altro esempio è una classe che incapsula l'i/o del file: il codice in Class_Terminate potrebbe tentare di svuotare e chiudere il file se è ancora aperto, il che può generare un errore.

Quindi è importante essere consapevoli che impostare un riferimento a un oggetto su Nothing può generare un errore e gestirlo di conseguenza (esattamente come dipenderà dalla tua applicazione - ad esempio potresti ignorare tali errori inserendo "On Error Resume Next" subito prima di " Impostato ...= Niente").

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top