Frage

In einem meiner VB6-Formulare erstelle ich mehrere andere Formularobjekte und speichere sie in Mitgliedsvariablen.

Private m_frm1 as MyForm
Private m_frm2 as MyForm

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

Mir ist aufgefallen, dass ich immer dann Speicher verliere, wenn dieses (übergeordnete) Formular erstellt und zerstört wird.Muss ich diese Mitgliedsvariablen zuweisen? Nothing In Form_Unload()?

Wann ist das im Allgemeinen erforderlich?

Gelöst:Dieses spezielle Speicherleck wurde behoben, als ich eine machte Unload auf den betreffenden Formularen, nicht wenn ich das Formular auf eingestellt habe Nothing.Ich habe es geschafft, einige andere Speicherlecks zu beseitigen, indem ich einige Instanzen von Klassenmodulen explizit auf gesetzt habe Nothing, sowie.

War es hilfreich?

Lösung

@Matt Dillard – Hat das Setzen dieser Werte auf „Nichts“ Ihren Speicherverlust behoben?

VB6 hat keinen formellen Garbage Collector, eher im Sinne von @Konrad Rudolph.

Der tatsächliche Aufruf von „unload“ auf Ihren Formularen scheint mir der beste Weg zu sein, um sicherzustellen, dass das Hauptformular bereinigt wird und dass jedes Unterformular seine Aktionen bereinigt.

Ich habe dies mit einem leeren Projekt und zwei leeren Formularen getestet.

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

Nach dem Ausführen bleiben beide Formulare sichtbar.Die Einstellung von „Frm“ auf „Nichts“ hat gut funktioniert...Nichts.

Nachdem frm auf nichts gesetzt wurde, ist der einzige offene Handle für dieses Formular die Referenz.

Unload Forms(1)

Sehe ich das Problem richtig?

  • Josh

Andere Tipps

Eigentlich implementiert VB6 RAII genau wie C++, was bedeutet, dass lokal deklarierte Referenzen automatisch auf gesetzt werden Nothing am Ende eines Blocks.Ebenso ist es sollen Mitgliederklassenvariablen werden nach der Ausführung automatisch zurückgesetzt Class_Terminate.Es gab jedoch mehrere Berichte, dass dies nicht zuverlässig geschieht.Ich kann mich an keinen strengen Test erinnern, aber es war schon immer die beste Vorgehensweise, Mitgliedsvariablen manuell zurückzusetzen.

@Martin

VB6 hatte eine „With/End With“-Anweisung, die „wie“ die Using()-Anweisung in C#.NET funktionierte.Und natürlich gilt: Je weniger globale Dinge Sie haben, desto besser für Sie.

With/End With funktioniert nicht wie die Using-Anweisung, es erfolgt kein „Dispose“ am Ende der Anweisung.

With/End With funktioniert in VB 6 genauso wie in VB.Net, es ist im Grunde eine Möglichkeit, den Aufruf von Objekteigenschaften/-methoden zu verknüpfen.z.B.

Mit acustomer .firstname = "John" .LastName = "Smith" endet mit

Objekte in VB verfügen über eine Referenzzählung.Das bedeutet, dass ein Objekt zählt, wie viele andere Objektvariablen eine Referenz darauf enthalten.Wenn keine Verweise auf das Objekt vorhanden sind, wird das Objekt (irgendwann) durch Müll gesammelt.Dieser Prozess ist Teil der COM-Spezifikation.

Wenn ein lokal instanziiertes Objekt den Gültigkeitsbereich verlässt (d. h.verlässt das Unterobjekt), sinkt sein Referenzzähler um eins, d. h. die Variable, die auf das Objekt verweist, wird zerstört.In den meisten Fällen müssen Sie beim Beenden eines Subs also nicht explizit ein Objekt auf Nothing setzen.

In allen anderen Fällen müssen Sie eine Objektvariable explizit auf Nothing setzen, um ihren Referenzzähler (um eins) zu verringern.Wenn Sie eine Objektvariable auf Nothing setzen, wird das Objekt nicht unbedingt zerstört. Sie müssen ALLE Referenzen auf Nothing setzen.Dieses Problem kann bei rekursiven Datenstrukturen besonders akut werden.

Ein weiteres Problem besteht bei der Verwendung des Schlüsselworts New in einer Objektvariablendeklaration.Ein Objekt wird nur bei der ersten Verwendung erstellt, nicht an der Stelle, an der das Schlüsselwort New verwendet wird.Durch die Verwendung des Schlüsselworts „New“ in der Deklaration wird das Objekt bei der ersten Verwendung jedes Mal neu erstellt, wenn sein Referenzzähler auf Null geht.Wenn Sie also ein Objekt auf Nothing setzen, wird es möglicherweise zerstört, aber das Objekt wird automatisch neu erstellt, wenn es erneut referenziert wird.Idealerweise sollten Sie nicht mit dem Schlüsselwort New deklarieren, sondern mit dem Operator New, der dieses Wiederauferstehungsverhalten nicht aufweist.

Streng genommen nie, aber es gibt dem Müllsammler einen starken Hinweis, die Dinge aufzuräumen.

Als Regel: Tun Sie dies jedes Mal, wenn Sie mit einem von Ihnen erstellten Objekt fertig sind.

Wenn Sie eine VB6-Referenz auf Nothing setzen, verringert sich die Anzahl der Referenzen, die VB für dieses Objekt hat.Genau dann, wenn die Anzahl Null ist, wird das Objekt zerstört.

Denken Sie nicht, dass, nur weil Sie „Nothing“ festlegen, „Müll gesammelt“ wird, wie in .NET

VB6 verwendet einen Referenzzähler.

Wir empfehlen Ihnen, instanziierte Objekte, die auf C/C++-Code und ähnliches verweisen, auf „Nothing“ zu setzen.Es ist lange her, seit ich VB6 berührt habe, aber ich erinnere mich, dass ich Dateien und Ressourcen auf Null gesetzt habe.

In beiden Fällen wird es nicht schaden (wenn es bereits Nothing war), aber das bedeutet nicht, dass das Objekt zerstört wird.

VB6 hatte eine „With/End With“-Anweisung, die „wie“ die Using()-Anweisung in C#.NET funktionierte.Und natürlich gilt: Je weniger globale Dinge Sie haben, desto besser für Sie.

Bedenken Sie, dass es in beiden Fällen manchmal teurer ist, ein großes Objekt zu erstellen, als eine Referenz am Leben zu halten und wiederzuverwenden.

Ich hatte vor einiger Zeit ein ähnliches Problem.Ich denke, es würde auch das Schließen der App verhindern, aber es könnte hier anwendbar sein.

Ich habe den alten Code aufgerufen und er sieht ungefähr so ​​aus:

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

Es kann sicherer sein, m_frm1 zu entladen.und nicht einfach auf Null setzen.

Ein wichtiger Punkt, der hier noch nicht erwähnt wurde, ist, dass das Setzen einer Objektreferenz auf Nothing dazu führt, dass der Destruktor des Objekts ausgeführt wird (Class_Terminate, wenn die Klasse in VB geschrieben wurde), wenn keine anderen Referenzen auf das Objekt vorhanden sind (Referenzanzahl ist Null). ).

In einigen Fällen, insbesondere bei Verwendung eines RAII-Musters, kann der Beendigungscode Code ausführen, der einen Fehler auslösen kann.Ich glaube, dass dies bei einigen ADODB-Klassen der Fall ist.Ein weiteres Beispiel ist eine Klasse, die Datei-E/A kapselt. Der Code in Class_Terminate versucht möglicherweise, die Datei zu leeren und zu schließen, wenn sie noch geöffnet ist, was zu einem Fehler führen kann.

Daher ist es wichtig, sich darüber im Klaren zu sein, dass das Setzen eines Objektverweises auf „Nothing“ einen Fehler auslösen kann, und diesen entsprechend zu behandeln (wie genau, hängt von Ihrer Anwendung ab – Sie können solche Fehler beispielsweise ignorieren, indem Sie „On Error Resume Next“ kurz vor „On Error Resume Next“ einfügen). Satz ...= Nichts").

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top