Collections et Objets - Quand et comment vider la mémoire [VBA] - VB/VBA/VBS - Programmation
Marsh Posté le 12-08-2014 à 15:16:08
VBA utilise un compteur de références pour faire office de garbage collector.
C'est à dire que dés qu'il n'existe plus aucune référence à ton objet, alors la mémoire consacrée à cet objet est libérée.
Quand tu écris
Code :
|
tu décrémentes le compteur de références de la mémoire pointée par "refObject". Dés que ce compteur arrive à 0, alors l'objet est supprimé.
Si tu veux que ton objet soit supprimé de ta collection, tu dois donc affecter "Nothing" à toutes les références de ton objet.
Marsh Posté le 12-08-2014 à 15:35:08
Merci pour ta réponse.
Mais je ne suis pas sûr de bien comprendre cette histoire de référence à un objet.
En gros, en début de procédure, je commence par créer 4 objets du premier type que j'affecte immédiatement à la collection qui les englobent:
Code :
|
Si je comprends bien ce que tu dis, à cet instant, la seule référence à mon objet de type Objet1 est celui de la collection.
Que se passe t'il si je crée 4 Objets1 dans ma collection1
Dois je attendre d'avoir supprimé les 4 de la collection pour que la mémoire soit libérée? Où la gestion se fait par instances de l'objet (4 donc)??
Aussi, j'ai testé un aut' truc:
Dans une procédure à part, j'ai mis:
Code :
|
.kill est un public sub de la ClassObjet1 qui appelle la procédure terminate
J'ai l'impression que là au moins,je force le "vidage" des variables utilisées par l'objet et donc, que j'ai un meilleur contrôle de l'utilisation des ressources.
Mais dans ta réponse, je comprends que collection1.item(i).remove devrait suffire (à condition que l'objet ne soit pas référencé ailleurs).
EDIT: je viens de retester en pas à pas et il semble bien qu'à partir du moment où je supprime l'objet de la collection1 à l'aide de remove, et comme cette collection est la seule à y fraire référence, le class terminate de mon objet s'execute bien
A priori, c'est tout bon pour moi
Marsh Posté le 12-08-2014 à 15:59:46
hush hush a écrit : Merci pour ta réponse.
|
- Ligne 1 : tu alloues de l'espace mémoire pour ton objet, et tu fais pointer la variable "Objet1" vers cette zone mémoire. Objet1 est donc une référence vers une zone de mémoire contenant une instance de ta classe ClassObjet1
- Ligne 2 : tu crées une autre référence vers cette zone mémoire via la méthode Add de ta collection. Cette zone de mémoire est donc référencée 2 fois
- Ligne 4 : tu supprimes une référence vers cette zone mémoire, qui est désormais pointée seulement par la référence contenue dans ta collection. Donc cette ligne ne permet pas de supprimer l'objet de la mémoire, elle supprime juste une référence.
hush hush a écrit :
|
Oui
hush hush a écrit :
|
Tu auras 4 références supplémentaires vers la mémoire de ton objet
hush hush a écrit :
|
Non, supprimer la collection (= affecter "Nothing" à la collection) supprime automatiquement tous les objets contenus dans la collection s'il n'existe pas d'autres références. C'est un comportement spécifique à VBA, ce n'est pas forcément le cas dans d'autres langages.
Si tu veux conserver ta collection mais supprimer uniquement l'objet, alors tu devras toi même supprimer toutes les références à cet objet (dans ta collection et ailleurs s'il en existe)
hush hush a écrit :
Mais dans ta réponse, je comprends que collection1.item(i).remove devrait suffire (à condition que l'objet ne soit pas référencé ailleurs). |
C'est ça. Le Remove() supprime la référence à l'objet contenue dans ta collection. Si c'est la dernière référence, alors la mémoire de l'objet sera libérée
Marsh Posté le 12-08-2014 à 16:18:51
Merci beaucoup pour tes réponses détaillées
J'ai une dernière question, puis j'arrête de t'embêter
Imaginons que je créer 4 objets Classeobjet1 selon la méthode exposée dans mon premier poste, à la sortie, je me retrouve avec une collection de 4 objets Classeobjet1.
Quand je .remove(i) un des objets de la collection, la méthode classe terminate (dans le module de classe objet1) s’exécute automatiquement:
-C'est logique car c'est la dernière et unique référence à cette instance de l'objet
-C'est illogique car il reste encore 3 autres références au même objet (les autres instances...)
Lequel de ces deux tirets est vrai?
Marsh Posté le 12-08-2014 à 16:45:57
hush hush a écrit : Imaginons que je créer 4 objets Classeobjet1 selon la méthode exposée dans mon premier poste, à la sortie, je me retrouve avec une collection de 4 objets Classeobjet1. Quand je .remove(i) un des objets de la collection, la méthode classe terminate (dans le module de classe objet1) s’exécute automatiquement: Lequel de ces deux tirets est vrai? |
La phrase en gras m'interpelle : est-ce que tu fais un "New Classobjet1" pour chaque item que tu ajoutes à ta collection, ou fais tu un seul "New", et 4 fois "Add" avec à chaque fois la même variable ?
Si c'est le cas, alors c'est normal que Terminate soit appelé car chaque New créé une nouvelle référence vers une nouvelle zone mémoire. Chaque référence est donc unique dans cette collection, et sa suppression entraine la libération de la mémoire associée.
Si tu ne créés qu'une seule référence (un seul "New" ) et que tu ajoutes 4 fois cette référence, alors ce n'est pas normal.
Marsh Posté le 12-08-2014 à 18:09:13
Harkonnen a écrit : |
Non, c'est la version normale
Merci pour tout, je crois que j'ai à peu près tout compris
Marsh Posté le 12-08-2014 à 19:23:28
Bonjour,
en dehors de Nothing, il y a bien l'instruction End nettoyant aussi la mémoire …
Si tu peux confirmer ou infirmer Harkonnen, merci …
Marsh Posté le 12-08-2014 à 20:19:24
End est extrêmement bourrin : ok, il ferme tous les fichiers ouverts et invalide toutes les références avant de fermer le programme.
Le problème de End, c'est qu'il n'appelle pas les méthodes Finalize ou Dispose pour tout invalider. Conséquence : toutes les ressources ouvertes sauf les fichiers ne sont pas libérées, et si le End a lieu dans un bloc Try/Catch, le Finally n'est pas appelé non plus.
Il faut donc bien prendre garde à libérer toutes les ressources non managées avant d'appeler End, qui de toute façon ne s'applique pas ici car hush hush ne voulait que supprimer un objet précis. End supprime tout de la pire des manières.
Marsh Posté le 13-08-2014 à 09:28:30
Tout à fait, l'idée est de pouvoir créer et supprimer des objets au cours de l'eau: chaque objet correspond au process d'un batch d'input.
Je ne veux surtout pas (pendant l'exectution du programme) de perdre TOUS les objets (sauf peut être à la fin, mais bon)
Ce que je pourrais faire maintenant, au lieu de supprimer les objets pour les remplacer par d'autre, c'est de les modifier, mais ça complique un peu ma gestion. Je préfère les supprimer et le recréer avec à chaque fois une nouvelle clé qui me permet de retrouver précisément où j'en suis dans mon programme.
Sinon, j'ai une autre question
Comme je vous le disais, certain de mes processus sont asynchrones. Il se trouve donc qu'assez souvent, aucun process VBA soient en exécution, qu'il attende la call back d'un des process en cours.
Le cas ne s'est pas encore produit mais je me demandais à quel moment le vba va décidé de tout vider, car pour le moment, mes variable continuent de contenir ce que je leur impute. (c'est le comportement souhaité).
Marsh Posté le 12-08-2014 à 12:44:45
Hello,
Je bosse sur un projet VBA et je découvre un peu les objets/collections d'objets.
J'ai commencé la programmation d'un module de classe d'objets (2 en fait) et pour chacun des types d'objets, j'ai crée des collections qui me permettent de les gérer en différents endroits du code.
Un des deux objets a un fonctionnement asynchrone, c'est à dire que le code VBA l'appelle, demande l’exécution d'un process puis se termine (le code vba).
Lorsque le process est terminé, un événement de l'objet se produit et appelle une procédure de mon code principal.
La question que je me pose est: à quel moment puis-je/dois je supprimer l'objet pour libérer la mémoire?
Est ce qu'il suffit d'utiliser la méthode .remove de la collection pour que l'objet soit effectivement supprimée et la mémoire allouée vidée??
J'ai essayé:
Set nomdelacollection.item(cléobjet) = nothing, mais ça ne passe pas..
J'ai peur que le .remove supprime l'objet uniquement de la collection mais reste "en vie" et ne se remet pas à zero...
Des idées?
Merci d'avance pour votre aide.