Wann muss ich in VB6 eine Variable auf "Nothing" setzen?

8

In einem meiner VB6-Formulare erstelle ich mehrere andere Form-Objekte und speichere sie in Elementvariablen.

%Vor%

Ich merke, dass ich immer dann Speicher verliere, wenn diese (Eltern-) Form erstellt und zerstört wird. Muss ich diese Membervariablen Nothing in Form_Unload() ?

zuweisen?

Im Allgemeinen, wann ist das erforderlich?

Gelöst: Dieser bestimmte Speicherverlust wurde behoben, wenn ich ein Unload auf den fraglichen Formularen tat, nicht wenn ich das Formular auf Nothing setzte. Es gelang mir, einige andere Speicherlecks zu entfernen, indem ich einige Instanzen von Klassenmodulen explizit auf Nothing setzte.

    
Matt Dillard 27.08.2008, 14:54
quelle

8 Antworten

5

@Matt Dillard - Haben Sie diese Einstellung auf nichts geändert, um Ihr Speicherleck zu beheben?

VB6 hat keinen formellen Müllsammler, mehr nach dem, was @Konrad Rudolph gesagt hat.

Das Aufrufen von Entladeoperationen für Formulare scheint mir der beste Weg zu sein, um sicherzustellen, dass das Hauptformular bereinigt wird und jedes Teilformular seine Aktionen bereinigt.

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

%Vor%

Nach dem Ausführen bleiben beide Formulare sichtbar. Einstellung frm zu nichts gut ... nichts.

Nach dem Setzen von frm auf nichts, ist der einzige Punkt, der für dieses Formular offen ist, der Verweis.

%Vor%

Sehe ich das Problem richtig?

  • Josh
Josh Miller 27.08.2008, 17:23
quelle
7

Tatsächlich implementiert VB6 RAII genau wie C ++, was bedeutet, dass lokal deklarierte Referenzen am Ende automatisch auf Nothing gesetzt werden von einem Block. Entsprechend sollte Memberklassenvariablen automatisch zurücksetzen, nachdem Class_Terminate ausgeführt wurde. Es gibt jedoch mehrere Berichte, dass dies nicht zuverlässig geschieht. Ich kann mich an keinen strengen Test erinnern, aber es war schon immer die beste Methode, Membervariablen manuell zurückzusetzen.

    
Konrad Rudolph 27.08.2008 15:27
quelle
4

@Martin

  
    

VB6 hatte eine "With / End With" -Anweisung, die ähnlich wie die Using () -Anweisung in C # .NET funktioniert. Und natürlich, je weniger globale Dinge du hast, desto besser für dich.

  

Wenn / End With nicht wie die Using-Anweisung funktioniert, wird am Ende der Anweisung nicht "Dispose" ausgegeben.

Mit / End Mit funktioniert in VB 6 genau wie in VB.Net, es ist im Grunde eine Möglichkeit, Objekteigenschaften / Methodenaufruf zu verknüpfen. z.B.

Mit einem Kunden   .FirstName="John"   .LastName="Schmied" Ende mit

    
BZ. 27.08.2008 15:11
quelle
4

Objekte in VB haben Referenzzählung. Dies bedeutet, dass ein Objekt eine Zählung darüber behält, wie viele andere Objektvariablen einen Verweis darauf enthalten. Wenn keine Verweise auf das Objekt vorhanden sind, wird das Objekt (möglicherweise) als Müll erfasst. Dieser Prozess ist Teil der COM-Spezifikation.

Wenn ein lokal instantiiertes Objekt den Gültigkeitsbereich verlässt (d. h. das Sub-Objekt verlässt), sinkt seine Referenzzahl normalerweise um eins, dh die Variable, die auf das Objekt verweist, wird zerstört. In den meisten Fällen müssen Sie daher beim Beenden eines Subs kein Objekt gleich Nothing setzen.

In allen anderen Fällen müssen Sie eine Objektvariable explizit auf Nothing setzen, um die Anzahl der Referenzen (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 weiterer Fehler ist, wenn das Schlüsselwort New in einer Objektvariablendeklaration verwendet wird. Ein Objekt wird nur bei der ersten Verwendung erstellt, nicht an dem Punkt, an dem das Schlüsselwort "Neu" verwendet wird. Wenn Sie das Schlüsselwort New in der Deklaration verwenden, wird das Objekt bei der ersten Verwendung jedes Mal neu erstellt, wenn der Referenzzähler auf Null gesetzt wird. 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 das Schlüsselwort New angeben, sondern den Operator New, der dieses Auferstehungsverhalten nicht aufweist.

    
Guillermo Phillips 29.09.2008 11:31
quelle
2

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

In der Regel: Mach es jedes Mal, wenn du mit einem von dir erstellten Objekt fertig bist .

    
Allain Lalonde 27.08.2008 15:05
quelle
2

Wenn Sie eine VB6-Referenz auf Nothing setzen, verringert sich die Anzahl der Refecenzen, die VB für dieses Objekt besitzt. Wenn und nur wenn die Anzahl Null ist, wird das Objekt zerstört.

Denken Sie nicht, dass, nur weil Sie auf Nothing gesetzt haben, es "Müll gesammelt" wie in .NET

sein wird

VB6 verwendet einen Referenzzähler.

Sie werden ermutigt, auf "Nothing" installierte Objekte zu setzen, die sich auf C / C ++ - Code und solche Sachen beziehen. Es ist lange her, seit ich VB6 berührt habe, aber ich erinnere mich daran, dass ich Dateien und Ressourcen auf nichts eingestellt habe.

In jedem Fall wird es nicht weh tun (wenn es schon Nichts war), aber das bedeutet nicht, dass das Objekt zerstört wird.

VB6 hatte eine "With / End With" -Anweisung, die ähnlich wie die Using () -Anweisung in C # .NET funktioniert. Und natürlich, je weniger globale Dinge du hast, desto besser für dich.

Denken Sie daran, dass in manchen Fällen das Erstellen eines großen Objekts teurer ist als das Beibehalten einer Referenz und deren Wiederverwendung.

    
Martin Marconcini 27.08.2008 15:07
quelle
2

Ich hatte ein ähnliches Problem wie vor einiger Zeit. Ich denke, es würde auch verhindern, dass die App geschlossen wird, aber es könnte hier anwendbar sein.

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

%Vor%

Es ist vielleicht sicherer, m_frm1 zu entladen. und nicht einfach auf nichts setzen.

    
Josh Miller 27.08.2008 15:07
quelle
2

Ein wichtiger Punkt, der hier noch nicht erwähnt wurde, ist, dass das Setzen eines Objektreferenz auf Nothing den Destruktor des Objekts ausführen wird (Class_Terminate, wenn die Klasse in VB geschrieben wurde), wenn keine weiteren Verweise auf das Objekt vorhanden sind (Referenz) count ist null).

In einigen Fällen, insbesondere bei Verwendung eines RAII-Musters, kann der Beendigungscode Code ausführen, der einen Fehler verursachen kann. Ich glaube, das ist bei einigen ADODB-Klassen der Fall. Ein anderes Beispiel ist eine Klasse, die Datei-E / A kapselt - der Code in Class_Terminate könnte versuchen, die Datei zu löschen und zu schließen, wenn sie noch offen ist, was zu einem Fehler führen kann.

Es ist also wichtig zu wissen, dass das Setzen eines Objektreferenz auf Nothing einen Fehler auslösen kann und dementsprechend behandelt werden kann (genau wie es von Ihrer Anwendung abhängt - zum Beispiel können Sie solche Fehler ignorieren, indem Sie "On Error Resume Next" einfügen) kurz vor "Set ... = Nothing").

    
Joe 22.07.2009 06:47
quelle

Tags und Links