Mémoire vive et objets
Accueil Remonter Appeler une procédure Mémoire vive et objets

 

 

Libérer les objets de la mémoire
par Marc Van den Berghen, Ivar B. Jessen et Jean-Pierre Martel

source : http://www.dbase.com/knowledgebase/dbulletin/bu20_c.htm

Introduction     

dBASE a été l'une des premières plate-forme de développement à bénéficier d'outils automatiques de nettoyage. Au fil des ans, ce service a été de plus en plus fiable au point que nous avons failli ne jamais avoir à nous soucier des objets orphelins en mémoire . Pourquoi devrait-on s'en soucier ? Laisser des objets en mémoire, sans pouvoir les manipuler revient à remplir la mémoire avec des éléments inutiles puisque l'on ne peut plus s'en servir. Si cela se produit de trop, on fini par saturer la mémoire et générer un plantage. Un type d'objet a besoin d'attentions spéciales c'est l'objet OLEAutoClient, il fera l'objet d'explications par ailleurs.

Les objets "Apoptosiques"

Pour chaque objet, dBASE maintient un compteur de référence. Principalement, le compteur de référence est une propriété cachée de type entier que dBASE augmente ou diminue en cas de besoin. Lorsque ce compteur arrive à zéro, l'objet se suicide (ou apoptose (1) ). Normalement, dBASE ne crée que des objets apoptosiques. C'est le mécanisme par lequel dBASE fais le nettoyage. Le nombre de références peut être connu par la méthode refCount(). Elle accepte un seul paramètre: le nom de référence de l'objet (sans les guillemets).


f = new form()
? refCount(f) // 1
g = f
? refCount(f) // 2
g = null
? refCount(f) // 1
f = null
? refCount(f) // Error - Expecting Object (Erreur - Attend un Objet)

 

Quel est le mécanisme exact par lequel l'objet commet l'apoptose? Selon une interview accordée au dBulletin par Marty Kay (le directeur de la recherche et du développement de la base de données), tous les objets dBASE héritent d'une référence interne comptant l'objet. La classe a une méthode d'augmentation et une méthode de décrémentation pour le compteur de référence. Dans la méthode de décrémentation, il existe un test pour voir si le compteur de référence atteint zéro (après la décrémentation). Lorsque c'est le cas, il appelle la méthode de destruction de l'objet qui effectue tout le nettoyage nécessaire. En fonction de la classe, ceci peut consister en la fermeture ou la libération des divers autres objets et / ou de structures de données, de désactiver les notifications d'autres objets, etc La dernière chose que le destructeur fait est de libérer la mémoire occupée par l'objet.

A) La libération "ordinaire" des objets dBASE

Tous les éléments (ou composants) visuels ont leur propre méthode release(). Ceci libère effectivement l'objet de la mémoire, retournant true en cas de réussite. Lorsque l'objet en comporte d'autres (un objet formulaire, un objet notebook ou un objet conteneur), tous les objets qui appartiennent à ce contenant sont également détruits.


f = new form()
f.entryfield1 = new entryfield(f)
? findInstance("Form")           // Object
? type("f")                      // "O" pour Object
? refCount(f)                   // 1

f.release()                      // appelle la méthode de destruction

? findInstance("Entryfield")     // rien
? type("f.entryfield1")          // "U" pour Undefined (non défini)
? refCount(f.entryfield1)        // Error - Attempt to access released object - Erreur - Tentative d'accès à un objet libéré

? findInstance("Form")           // rien
? type("f")                      // "O" pour objet
? refCount(f)                    // 1

 

Dans le code ci-dessus, findInstance("Form") signale que l'objet Form n'existe plus. Pourtant, la commande type("f") indique que la variable f est un objet. Pourquoi? Parce que la variable passée à type() contient une valeur de type "Object" ou "O" et une valeur qui sert à pointer sur un objet. Le pointeur se trouve toujours dans la variable, et n'a pas été modifié en appelant la méthode release() de l' objet.

En raison de l'efficacité des outils de nettoyage de dBASE , la méthode release () est rarement nécessaire. dBASE possède également une commande release object. Elle fait la même chose que la méthode release(). Cette commande peut être utilisée pour les objets (comme les requêtes) qui ne disposent pas d'une méthode release().


q = new query()
? findInstance("Query") // Object ("Query")
? type("q")             // "O" pour objet
? ? refCount(q)         // 1

release object q

? findInstance("Query") // rien
? type("q")             // "O" pour objet
? refCount(q)           // 1

release q              // ici nous libérons la variable q

? findInstance("Query") // rien
? type("q")             // "U" pour Undefined, non défini
? refCount(q)           // Error: Variable undefined -(Erreur: variable indéfinie)

 

B) La libération de la référence de l'objet de référence


f = new form()

 

La ligne ci-dessus fait deux choses: elle crée un objet et une référence (ou un pointeur) à cet objet. En fait, la variable f contient l'adresse en mémoire de l'endroit où se trouve l'objet form.

Il y a deux façons de détruire une référence à un objet:

  1. On peut vider la variable ou modifier sa valeur en quelque chose d'autre (par exemple : f = null, f = "", f = 0, f = 5).

  2. Nous pouvons libérer la variable (c'est-à-dire release f).

La seule différence est que la commande release supprime également la variable f .

Si dBASE ne disposait pas de son système de nettoyage automatique, il serait dangereux de supprimer un pointeur sans d'abord supprimer l'objet pointé par le pointeur : nous couperions le cordon ombilical qui relie la variable à l'objet, sans détruire l'objet lui-même. Ce dernier deviendrait un élément orphelin de la mémoire, flottant dans la RAM. Cela ne se passe pas, car dès que l'objet perd son dernier objet de référence, il commet l'apoptose.


f = new form()
? findInstance("Form") // Objet
? type("f")            // "O" pour objet
? refCount(f)          // 1

f = null

? findInstance("form") // rien
? type("f")            // "U" pour Undefined - indefini
? refCount(f)          // Error: Expecting object - Erreur: objet attendu

 

Comme on peut le voir, annuler la référence de l'objet ne perturbe pas l'opération automatique de nettoyage : au contraire, il déclenche l'apoptose (suicide) de l'objet.

 

La suite de l'article traite de la suppression des objets OLE., le principe est le même, suppression de l'objet créant la liaison puis de la variable. Voir le texte original.


Notes de traduction :

Note 1 : On nomme apoptose (ou mort cellulaire programmée, ou suicide cellulaire) le processus par lequel des cellules déclenchent leur auto-destruction en réponse à un signal