Bopm propose une interface aux fonctions classiques d'accès à la mémoire telles que malloc et free.
Cette interface permet :
Les fonctions d'accès à la mémoire .
Les fonctions bopmMalloc, bopmFree, bopmCalloc, bopRealloc peuvent être appelées
de la même manière que, respectivement, malloc, free, calloc et realloc,
voir la documentation de ces fonctions : malloc(3).
Ces fonctions ne retournent que si l'allocation s'est effectuée correctement, dans le cas contraire la
fonction abort(3) est appelée et le programme est par defaut terminé avec un "core dump"
après un message sur stderr precisant la fonction ayant appelé Bopm.
Notons que le signal SIGABRT peut être "atrappé" par un "signal handler".
Bien qu'actuellement "cela marche quand même", la mémoire allouée avec Bopm doit être libérée avec bopmFree et bopmfree ne doit liberer que la mémoire allouée par Bopm
Ces oublis peuvent être faciles à corriger lorsqu'ils ne masquent pas de déficiences de conception dans le logiciel, et lorsque le programmeur a suffisamment d'indications pour trouver l'allocation en cause.
Bopm propose une manière excessivement simple d'être averti des allocations non liberées, la fonction
affiche sur stderr le nombre d'allocations faites par l'intermédiaire de bopm et non libérées
Lorsque le programmeur prend le soin de liberer en fin de programme toutes les allocations restantes
(ce qui est inutile voir couteux par ailleurs, l'espace d'adressage étant de toute manière supprimé
en fin du processus), bopmMem devrait indiquer que nombre d'allocations en cours est 0.
Cela n'indique pas l'endroit où a été allouée la mémoire non liberée, mais si cette fonction est utilisée
pendant toutes les phases de test d'un logiciel, le programmeur saura que c'est probablement dans une
des modifications qu'il a faites depuis les derniers tests.
Cela peut cependant ne pas suffire, la fonction bopmTrace permet de connaitre les appels de bopmMalloc
( ou bopmCalloc ou encore bopmRealloc ) ayant alloué de la mémoire non libérée par bopmFree.
bopmTrace permet d'activer le logging des allocations et des desallocations de mémoire sur un fichier
dont le nom est donné par la variable d'environnement BOP_MTRACE. Son pendant bopmUntrace arrête ce logging
et ferme le fichier.
Ces fonctions se sont amplement inspirées des fonctions GNU mtrace() et untrace().
La raison qui m'a fait écrire bopmTrace, c'est que mtrace m'indiquait - bien évidemment - que la mémoire
non libérée avait été allouée dans bopmMalloc, ce dont je me doutais déjà... Du moins j'aurais du m'en douter.
Un autre interêt de bopmTrace est de ne prendre en compte que les allocations effectuées par bopm,
lorsque l'on utilise mtrace, toutes les allocations y compris celles effectuées par les bibliothèques
que l'on utilise sont loggées.
Le format des informations en sortie est également un peu différent, mais là cela devient anecdotique.
Permet le logging des appels des fonctions d'allocation et de libération de mémoire de bopm.
Le logging est effectué si et seulement si la variable BOP_MTRACE est déclarée dans l'environnement.
Le logging est placé sur un fichier ouvert en écriture (flag "w" donc tronqué s'il existe)
dont le nom est indiqué dans la variable BOP_MTRACE.
Si le logging est déjà activé à l'appel de cette fonction, elle ne fait rien.
Permet d'arrêter le logging des appels des fonctions d'allocation et de libération de mémoire de bopm.
Le fichier log est fermé.
Si le logging est déjà desactivé à l'appel de cette fonction, elle ne fait rien.
Ces logs sont destinées à être analysées par le programme bopmtrace qui indique, entre autres informations utiles,
l'endroit où a été alloué de la mémoire non libérée.
Accessoirement il indique lorsque la mémoire est libérée 2 fois et des choses plus étranges encore.
Il se trouve dans le package bop-utils. Si vous l'avez installé, ce qui est recommendé aux utilisateurs de Bop,
son utilisation est décrite par une page man bopmtrace(1)
Notons que bopmTrace tout comme bopmMem peut être utilisé sans problème dans un programme en production
dans la mesure où la variable BOP_MTRACE n'est pas trouvée dans l'environnement.
Le programme suivant contient des memory leaks, l'utilisation de bopmMem et de bopmtrace permet de les mettre en évidence
et de les localiser.
la variable "TESTS" du preprocesseur permet, lorsqu'elle est mise à O d'éviter les liberations de mémoire en fin de programme.
// this program is public domain // // usage : boptest [num] // // this program forgets to free <num> allocations (default 10) // // Do *NOT* FIXME : // don't free mem0 // memory leaks in the iteration // #include <bop.2/bop.h> // set to 0 for production. #define TESTS 1 int main ( int argc, char ** argv ) { char * mem0 ; char * mem1 ; char * mem2 ; int iter = 10 ; // default iteration # #if ( TESTS > 0 ) bopmTrace( ) ; #endif mem0 = bopmMalloc( 4096 ) ; mem1 = bopmMalloc( 2048 ) ; if ( argc > 1 ) { iter = atoi( argv[1] ) ; } // main and only loop for ( ; iter-- > 0 ; ) { mem2 = bopmMalloc( 512 ) ; } #if ( TESTS > 0 ) // free unused memory bopmFree( mem1 ) ; bopmFree( mem2 ) ; bopmMem( ) ; #endif return ( EXIT_SUCCESS ) ; }Une fois compilé et linké avec Bop, si on utilise ce programme ainsi :
$ export BOP_MTRACE=mem.log $ boptest 3Le programme affichera sur stderr :
Current allocations : 3Ce qui nous indique la présence de memory leaks.
Pour trouver leur origine, nous pouvons nous réfèrer au contenu du fichier mem.log.
A 0804A170 4096 boptest.c main 29 A 0804B178 2048 boptest.c main 30 A 0804B980 512 boptest.c main 40 A 0804BB88 512 boptest.c main 40 A 0804BD90 512 boptest.c main 40 F 0804B178 boptest.c main 45 F 0804BD90 boptest.c main 46Pour un programme pourtant bien trivial, ce n'est pas très parlant, l'utilisation du programme bopmtrace permet d'analyser le fichier mem.log.
$ bopmtrace < mem.log 1 Not Freed 0804A170 4096 boptest.c main 29 3 Not Freed 0804B980 512 boptest.c main 40 4 Not Freed 0804BB88 512 boptest.c main 40Nous connaissons maintenant l'endroit où a été allouée la mémoire non libérée.
Reste à faire.
Voir aussi.
malloc(3) , mtrace(3), mtrace(1),
Chez moi la documentation en html se trouve sur :
file:/usr/share/doc/glibc-doc/html/libc_3.html#SEC19
http://freefeed/bop/bopm.php (13/12/2006) Copyright © 2004 Patrick Davalan.
Il est permis de copier, distribuer et/ou modifier ce document selon les termes et condiions de la GNU Free Documentation License, version 1.2 ou toute version ulterieure publiée par la Free Software Foundation.
Warning: fopen(/home/web/patrick/data/locks/bop%2Fbopm.php): failed to open stream: No such file or directory in /home/web/patrick/include/functions.inc on line 315