Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

libération de la mémoire associée aux expressions incluses dans le code d'une fonction

5 réponses
Avatar
Marc G
Bonjour à tous,
J'ai écrit un compilo (enfin un programme qui génère du bytecode) et j'ai
une difficulté avec la libération de la mémoire associée aux expressions
incluses dans les fonctions.
Les instructions dans la portée globale d'un programme sont supprimées après
exécution => idem pour les expressions associées et pas de problème pour la
mémoire.
Pour les fonctions, c'est différent puisque les instructions sont conservées
(les fonctions sont enregistrées dans une table puis supprimées uniquement à
la fin de l'exécution du programme). Je n'ai pas de problème de fuite de
mémoire, mais
1) soit je me traine le "contenu" de certaines expressions (des temporaires)
évaluées dans la fonction lorsque celle-ci a été appelée ;
2) soit je suis obligé d'appeler un "nettoyeur" après chaque évaluation des
expressions - c'est pas trop compliqué mais ça m'embête pour la performance
:-()

=> MA QUESTION :
est-ce que vous savez comment ce problème est géré dans les langages ?
la norme dit-elle quelque chose la-dessus ?

ai-je été clair ? suis-je HS ?
Merci à vous.
Marc

5 réponses

Avatar
Stan
On 18 juin, 16:27, "Marc G" wrote:

ai-je été clair ? suis-je HS ?
Merci à vous.
Marc



Un exemple de code aurait été grandement utile...

--
-Stan
Avatar
Stan
On 18 juin, 16:27, "Marc G" wrote:

ai-je été clair ? suis-je HS ?
Merci à vous.
Marc



Un exemple de code aurait été grandement utile...

--
-Stan
Avatar
Stan
On 18 juin, 16:27, "Marc G" wrote:

ai-je été clair ? suis-je HS ?
Merci à vous.
Marc



Un exemple de code aurait été grandement utile...

--
-Stan
Avatar
pjb
"Marc G" writes:

Bonjour à tous,
J'ai écrit un compilo (enfin un programme qui génère du bytecode) et
j'ai une difficulté avec la libération de la mémoire associée aux
expressions incluses dans les fonctions.

Les instructions dans la portée globale d'un programme sont supprimées
après exécution => idem pour les expressions associées et pas de
problème pour la mémoire.



Alors on ne peut pas exécuter le programme deux fois...

Pour les fonctions, c'est différent puisque les instructions sont
conservées (les fonctions sont enregistrées dans une table puis
supprimées uniquement à la fin de l'exécution du programme). Je n'ai
pas de problème de fuite de mémoire, mais
1) soit je me traine le "contenu" de certaines expressions (des
temporaires) évaluées dans la fonction lorsque celle-ci a été appelée
;



C'est quoi le contenu d'une expression?

Je connais l'expression elle même (l'arbre syntaxique), le code
généré, la valeur calculée par l'expression, mais le "contenu", je ne
vois pas.

S'il s'agit des valeurs intermédiaires, normalement elles sont
stoquées dans les régistres du processeur (de la machine virtuelle).
Si il n'y a pas assez de régistre, alors elles sont stoquées sur la
pile. Il peut ne pas y avoir de régistre du tout, on a alors une
"machine à pile" comme machine virtuelle.

Lorsque les valeurs intermédiaires sont stoquées dans des régistres,
il n'y a rien à faire de spécial, on sait quand la valeur n'est plus
utile, et donc quand le régistre peut être réutiliser pour une autre
valeur.

Quand à la pile, les valeurs intermédiaires sont dépilées au fur et à
mesure qu'elles sont consommées pour produire al valeur finale, c'est
donc encore plus simple.


2) soit je suis obligé d'appeler un "nettoyeur" après chaque
évaluation des expressions - c'est pas trop compliqué mais ça m'embête
pour la performance :-()



Bon, si on gère des valeurs qui ne tiennent pas dans un régistre (ou
un mot de la pile), on va bien sur l'allouer sur le tas, mais alors
c'est géré comme pour toutes les autres valeurs allouées sur le tas :
un ramasse miette fera le ménage le moment voulu.


=> MA QUESTION :
est-ce que vous savez comment ce problème est géré dans les langages ?



Le Dragon Book
http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools
traite de ces sujets, et sa dernière édition ajoute même un chapitre
sur la gestion de la mémoire (par ramasse miette).


la norme dit-elle quelque chose la-dessus ?



Non. Les normes des languages ne spécifient pas le _comment_ mais le
_quoi_. Pas comment le langage doit être implémenté, mais en quoi
consiste le langage.


ai-je été clair ?



Plus ou moins.


suis-je HS ?



Ça dépend. C'est un compilateur C++?

--
__Pascal Bourguignon__
Avatar
Marc G
je précise : le programme est écrit intégralement en C++ standart :-)
Alors on ne peut pas exécuter le programme deux fois...



si, le programme est compilé puis immédiatement exécuté
pour l'exécuter 2 fois, tu cliques 2 fois sur le bouton exécuter :-)

C'est quoi le contenu d'une expression?


Quelques précisions :
tous les objets manipulés par mon compilateur (par le programme donc)
dérivent d'une classe unique CObject
les opérateurs à appliquer sont déterminés à la compilation par le pattern
du double-dispatch
tous les objets sont alloués dans le tas et les opérateurs qui retournent
habituellement une valeur (comme +) retournent un objet alloué dans le tas

ce que j'appelle contenu d'une expression, c'est sa valeur : un ptr alloué
dans le tas dérivé de CObject
mon langage a aussi des instructions (ex : instruction for) qui manipulent
ou non des expressions

Bon, si on gère des valeurs qui ne tiennent pas dans un régistre (ou
un mot de la pile), on va bien sur l'allouer sur le tas, mais alors
c'est géré comme pour toutes les autres valeurs allouées sur le tas :
un ramasse miette fera le ménage le moment voulu.



un smart ptr me suffit, j'ai pas de référence circulaire

je viens de trouver la solution à mon problème :
j'avais bien séparé les objets manipulés par le programme des variables qui
les représentent, en souhaitant faire des optimisations (car j'ai parfois de
"gros" objets)
exemple d'optimisation :
x=a+b+c;
1/ je calcule a+b => expression représentée par une variable temporaire t
2/ t+c => t+=c car t est un temporaire
3/ x=t => je libère la mémoire allouée à x et je récupère directement
l'adresse de t car c'est un temporaire

donc j'ai dérivé un ensemble de classes de CVariable :
CVariableTemporaire/CVariablePasTemporaire/CVariableLiteral/CVariableIdentifier/CVariablePropriete/CVariableReference
etc..
par le pattern du double-dispatch, j'optimise à la compilation
en gros, à la compilation, il y a 2 fois utilisation du pattern du
double-dispatch : sur la nature des variables et sur la nature des objets

quand j'execute une instruction dans le contexte global (de mon programme),
je la détruit immédiatement après (donc les expressions éventuelles
associées sont aussi libérées)
quand dans mon programme je définis une fonction, je crée le bytecode
associé et le stocke quelque part
et quand j'appelle la fonction, je ne détruit pas son code à l'exécution !
d'où le problème de la présence dans les instructions de la fonction
d'expressions évaluées associées à des temporaires (les autres sont libérées
via un contexte par exemple)

je viens juste de réaliser que je savais exactement la nature de la variable
associée à une expression (je veux dire temporaire ou non) et qu'à la fin de
l'exécution d'une instruction, je pouvais libérer les valeurs associées aux
expressions représentées par des temporaires

=> mon problème est résolu
je te remercie d'avoir pris le temps de me répondre et j'espère que mon
exposé est clair, pas trop stupide, voir intéressant :-)
Marc