Question

Dans l'un de mes formulaires VB6, je crée plusieurs autres objets Form et les stocke dans des variables membres.

Private m_frm1 as MyForm
Private m_frm2 as MyForm

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

Je remarque que je perds de la mémoire chaque fois que ce formulaire (parent) est créé et détruit.Est-il nécessaire pour moi d'attribuer ces variables membres à Nothing dans Form_Unload()?

En général, quand est-ce nécessaire ?

RÉSOLU :Cette fuite de mémoire particulière a été corrigée lorsque j'ai effectué un Unload sur les formulaires en question, pas lorsque je règle le formulaire sur Nothing.J'ai réussi à supprimer quelques autres fuites de mémoire en définissant explicitement certaines instances de modules de classe sur Nothing, aussi.

Était-ce utile?

La solution

@Matt Dillard - Est-ce que leur réglage sur rien a résolu votre fuite de mémoire ?

VB6 n'a pas de garbage collector formel, plus dans le sens de ce que @Konrad Rudolph a dit.

En fait, appeler unload sur vos formulaires me semble être le meilleur moyen de garantir que le formulaire principal est nettoyé et que chaque sous-formulaire nettoie ses actions.

J'ai testé cela avec un projet vierge et deux formulaires vierges.

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

Après l'exécution, les deux formulaires restent visibles.mettre frm sur rien a bien fonctionné...rien.

Après avoir défini frm sur rien, le seul handle ouvert à ce formulaire est via la référence.

Unload Forms(1)

Est-ce que je vois correctement le problème ?

  • Josh

Autres conseils

En fait, VB6 implémente RAII tout comme C++, ce qui signifie que les références déclarées localement sont automatiquement définies sur Nothing à la fin d'un bloc.De même, il devrait réinitialiser automatiquement les variables de classe membre après l'exécution Class_Terminate.Cependant, plusieurs rapports indiquent que cela n'est pas fait de manière fiable.Je ne me souviens d'aucun test rigoureux, mais il a toujours été préférable de réinitialiser manuellement les variables membres.

@Martin

VB6 avait une instruction "With/End With" qui fonctionnait "comme" l'instruction Using() en C#.NET.Et bien sûr, moins vous avez de choses globales, mieux c'est pour vous.

With/End With ne fonctionne pas comme l'instruction Using, il ne "Dispose" pas à la fin de l'instruction.

With/End With fonctionne dans VB 6 tout comme dans VB.Net, il s'agit essentiellement d'un moyen de raccourcir les appels de propriétés/méthodes d'objet.par exemple.

Avec ACOSURE.

Les objets en VB ont un comptage de références.Cela signifie qu'un objet compte le nombre d'autres variables d'objet qui y font référence.Lorsqu'il n'y a aucune référence à l'objet, l'objet est récupéré (éventuellement).Ce processus fait partie de la spécification COM.

Habituellement, lorsqu'un objet instancié localement sort de sa portée (c'est-à-direquitte le sub), son compteur de références diminue de un, autrement dit la variable référençant l'objet est détruite.Ainsi, dans la plupart des cas, vous n'aurez pas besoin de définir explicitement un objet égal à Nothing en quittant un Sub.

Dans tous les autres cas, vous devez définir explicitement une variable objet sur Nothing, afin de diminuer son nombre de références (d'une).Définir une variable d'objet sur Nothing ne détruira pas nécessairement l'objet, vous devez définir TOUTES les références sur Nothing.Ce problème peut devenir particulièrement aigu avec les structures de données récursives.

Un autre piège est l'utilisation du mot-clé New dans une déclaration de variable objet.Un objet n'est créé que lors de la première utilisation, et non au moment où le mot-clé New est utilisé.L'utilisation du mot-clé New dans la déclaration recréera l'objet lors de la première utilisation chaque fois que son nombre de références atteint zéro.Ainsi, définir un objet sur Nothing peut le détruire, mais l'objet sera automatiquement recréé s'il est à nouveau référencé.Idéalement, vous ne devriez pas déclarer en utilisant le mot-clé New, mais en utilisant l'opérateur New qui n'a pas ce comportement de résurrection.

Jamais à proprement parler, mais cela donne au ramasse-miettes un indice fort pour nettoyer les choses.

Comme règle: faites-le chaque fois que vous avez terminé avec un objet que vous avez créé.

Définir une référence VB6 sur Nothing diminue le nombre de références que VB a pour cet objet.Si et seulement si le décompte est nul, alors l'objet sera détruit.

Ne pensez pas que simplement parce que vous avez défini sur Nothing, ce sera une "garbage collected" comme dans .NET.

VB6 utilise un compteur de référence.

Nous vous encourageons à définir sur "Rien" les objets instanciés qui font référence au code C/C++ et à des trucs comme ça.Cela fait longtemps que je n'ai pas touché à VB6, mais je me souviens avoir défini les fichiers et les ressources sur rien.

Dans les deux cas, cela ne fera pas de mal (si c'était déjà Rien), mais cela ne signifie pas que l'objet sera détruit.

VB6 avait une instruction "With/End With" qui fonctionnait "comme" l'instruction Using() en C#.NET.Et bien sûr, moins vous avez de choses globales, mieux c'est pour vous.

N'oubliez pas que, dans les deux cas, créer un objet volumineux coûte parfois plus cher que de conserver une référence en vie et de la réutiliser.

J'ai eu un problème similaire à celui-ci il y a quelque temps.Il me semble que cela empêcherait également la fermeture de l'application, mais cela pourrait être applicable ici.

J'ai récupéré l'ancien code et il ressemble à ceci :

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

Il peut être plus sûr de décharger le m_frm1.et pas simplement le mettre à néant.

Un point important qui n'a pas encore été mentionné ici est que définir une référence d'objet sur Nothing entraînera l'exécution du destructeur de l'objet (Class_Terminate si la classe a été écrite en VB) s'il n'y a pas d'autres références à l'objet (le nombre de références est nul ).

Dans certains cas, notamment lors de l'utilisation d'un modèle RAII, le code de terminaison peut exécuter du code susceptible de générer une erreur.Je pense que c'est le cas de certaines classes ADODB.Un autre exemple est une classe qui encapsule les E/S de fichier : le code dans Class_Terminate peut tenter de vider et de fermer le fichier s'il est toujours ouvert, ce qui peut générer une erreur.

Il est donc important d'être conscient que définir une référence d'objet sur Nothing peut générer une erreur et la gérer en conséquence (la manière exacte dépendra de votre application - par exemple, vous pouvez ignorer ces erreurs en insérant "On Error Resume Next" juste avant " Ensemble ...= Rien").

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top