Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2304 connectés 

  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [VBA] Collections et Objets - Quand et comment vider la mémoire

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[VBA] Collections et Objets - Quand et comment vider la mémoire

n°2235445
hush hush
je savais que ça te plairait
Posté le 12-08-2014 à 12:44:45  profilanswer
 

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.

mood
Publicité
Posté le 12-08-2014 à 12:44:45  profilanswer
 

n°2235461
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-08-2014 à 15:16:08  profilanswer
 

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 :
  1. Set refObject = Nothing


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.


---------------
J'ai un string dans l'array (Paris Hilton)
n°2235464
hush hush
je savais que ça te plairait
Posté le 12-08-2014 à 15:35:08  profilanswer
 

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 :
  1. Set Objet1 = New ClassObjet1
  2.         Collection1.Add Item:=Objet1, Key:=cleunique
  3.          .../execution de procédure/propriétés de l'objet
  4.         Set Objet1 = Nothing 'Je tue l'objet qui m'a permis de créer celui de la collection auquel j'aurais accès ultérieurement directement depuis la collection


 
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 :
  1. Collection1.Item(i).kill
  2.     Collection1.remove(i) 'Méthode de la collection pour virer l'objet en question


.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
:jap:

Message cité 1 fois
Message édité par hush hush le 12-08-2014 à 15:42:22
n°2235469
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-08-2014 à 15:59:46  profilanswer
 

hush hush a écrit :

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 :
  1. Set Objet1 = New ClassObjet1
  2.         Collection1.Add Item:=Objet1, Key:=cleunique
  3.          .../execution de procédure/propriétés de l'objet
  4.         Set Objet1 = Nothing 'Je tue l'objet qui m'a permis de créer celui de la collection auquel j'aurais accès ultérieurement directement depuis la collection




- 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 :


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.


Oui

 
hush hush a écrit :


Que se passe t'il si je crée 4 Objets1 dans ma collection1


Tu auras 4 références supplémentaires vers la mémoire de ton objet

 
hush hush a écrit :


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)??


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 :


Aussi, j'ai testé un aut' truc:
Dans une procédure à part, j'ai mis:

Code :
  1. Collection1.Item(i).kill
  2.     Collection1.remove(i) 'Méthode de la collection pour virer l'objet en question


.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).


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


Message édité par Harkonnen le 12-08-2014 à 16:00:16

---------------
J'ai un string dans l'array (Paris Hilton)
n°2235470
hush hush
je savais que ça te plairait
Posté le 12-08-2014 à 16:18:51  profilanswer
 

Merci beaucoup pour tes réponses détaillées :)
J'ai une dernière question, puis j'arrête de t'embêter :o
 
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? :o

Message cité 1 fois
Message édité par hush hush le 12-08-2014 à 16:20:09
n°2235471
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-08-2014 à 16:45:57  profilanswer
 

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:
-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? :o


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.

Message cité 1 fois
Message édité par Harkonnen le 12-08-2014 à 16:46:33

---------------
J'ai un string dans l'array (Paris Hilton)
n°2235483
hush hush
je savais que ça te plairait
Posté le 12-08-2014 à 18:09:13  profilanswer
 

Harkonnen a écrit :


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.


 
Non, c'est la version normale ;)
Merci pour tout, je crois que j'ai à peu près tout compris :jap:

n°2235491
Marc L
Posté le 12-08-2014 à 19:23:28  profilanswer
 

 
           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 …
 

n°2235493
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 12-08-2014 à 20:19:24  profilanswer
 

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.


---------------
J'ai un string dans l'array (Paris Hilton)
n°2235521
hush hush
je savais que ça te plairait
Posté le 13-08-2014 à 09:28:30  profilanswer
 

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  :D  
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é).


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [VBA] Collections et Objets - Quand et comment vider la mémoire

 

Sujets relatifs
[VBA] - fonction FIND associée à la recherche d'une date[RESOLU ] [VBA] ERREUR 91 - FINDNEXT
[RESOLU] [VBA] - EXCEL 2010 - Optimisation de codeHELP pour comparaison de cellules VBA
VBA - creer tableau dans wordL'indice n'appartient pas à la sélection, VBA Excel
Demande de réunion VBA Excel/OutlookLiens Hypertexte dans Listbox VBA
Help SVP "sous-répertoires VBA"Protection feuille VBA sauf userform
Plus de sujets relatifs à : [VBA] Collections et Objets - Quand et comment vider la mémoire


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR