La plomberie facile avec mtrace
Par Jean-Seb le lundi 22 février 2010, 21:37 - Coding - Lien permanent
Le C et les fuites mémoires, c'est comme une vieille complainte
sentimentale.
Avec mtrace, et sa couche maxi-absorbante, finissez-en
avec l'incontinence de vos programmes.
mtrace n'est pas disponible en pharmacie, uniquement dans
les bonnes libc.
Ma mémoire prend la fuite!
- Je ne vous fait pas une tartine sur les problèmes de gestion mémoire en C.
- Si vous avez approché un compilateur C un jour de votre vie, vous savez de quoi je parle.
- Pour prévenir les problèmes de fuite mémoire, il existe plusieurs méthodes.
Je ne fais rien
- Ne rigolez pas, un OS bien conçu est censé vous rendre la mémoire à la sortie de votre programme.
- Bon alors, on fait comme ça ?
- Non, on ne fait pas comme ça. On passe toujours un coup de balai avant de quitter un programme, question de savoir-vivre et d'éducation.
- Il y a également le fait qu'on ne sait jamais vraiment où le programme finira par tourner, ni si l'OS réussira réellement à récuperer toute la mémoire.
J'écris mon gestionnaire mémoire
- Allez, on l'a tous fait un jour ou l'autre.
- Ou comment finir avec un wrapper de malloc/free plus ou moins élaboré, qui génère de jolies listes d'alllocations/libérations.
- Ce n'est pas forcément une mauvaise idée. C'est surtout délicat à gérer pour toutes sortes de raisons (je ne développe pas, si vous ne comprenez pas, essayez de faire le votre).
- L'insensé tenant vraiment à explorer la Voie de l'Insomnie pourra toujours
commencer par :
man malloc_hook.
J'utilise mtrace
- Et c'est la prise de conscience sur un titre judicieusement choisi.
mtrace, principe et utilisation
Prérequis
- Une libc GNU.
- Un compilateur GNU.
Principe
- Le principe consiste à intercepter les appels à malloc et à free, et à tenir registre des allocations/libérations de mémoire.
- Pour cela, vous initialiserez le wrapper de la libc avec
mtrace(), et vous appellerez en sortiemuntrace().
Utilisation
- Il suffit d'inclure
mcheck.het vous pourrez utiliser les deux fonctions requises.mtrace: avant tout malloc().muntrace: après le dernier free().
- Vous aurez également besoin d'une variable shell, pour indiquer où écrire
le fichier de log.
export MALLOC_TRACE = /path/to/log.txt
- Une autre variable shell peut être utilisée:
MALLOC_CHECK- Normalement, son usage est d'indiquer le niveau de log.
export MALLOC_CHECK = 2: fait planter le programme si erreur malloc (je tenais à vous faire partager cette découverte).
- Un script Perl (mtrace) pour mettre en forme le fichier de log.
L'exemple tant attendu
Source pour nos essais
/* mtrace.c */
#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>
int main(void)
{
mtrace();
char *freed = malloc(1024);
char *leaked = malloc(1024);
if (freed) free(freed);
muntrace();
return 0;
}
- Pour compiler ce source, rien de spécial.
gcc -g -Wall mtrace.c -o mtrace- N'oubliez pas -g pour avoir les symboles dans la sortie de mtrace.
- Et pour le lancer:
MALLOC_TRACE=/tmp/mtrace.log
./mtrace- Le prompt revient, pas de plantages, donc, pas de problèmes.
- Vraiment ?
Utilisation du script Perl mtrace
- Tout d'abord, voyons à quoi ressemble le fichier log.
~test$ cat /tmp/mtrace.log = Start @ ./mtrace:[0x40060f] + 0x1ea7460 0x400 @ ./mtrace:[0x40061d] + 0x1ea7870 0x400 @ ./mtrace:[0x400631] - 0x1ea7460 = End
- De ce qui précède, on peut deviner aisément que le bloc mémoire situé à
0x1ea7870 n'a pas été libéré.
- Nous allons cependant rendre plus parlant ce fichier.
- Le script mtrace s'invoque avec en paramètres l'exécutable à analyser (pour ses symboles), et le fichier log.
~test$ MALLOC_TRACE="/tmp/mtrace.log" mtrace ./mtrace /tmp/mtrace.log
Memory not freed:
-----------------
Address Size Caller
0x0000000001cb6870 0x400 at /home/jseb/test/mtrace.c:12
- Voila qui est plus parlant.
- La ligne indiquée correspond au malloc() sans free() correspondant.
mtrace n'est cependant pas Dieu le Père Tout Puissant
- mtrace ne vous protégera bien sûr pas des écrasements mémoire durant l'exécution de votre programme.
- De même, les problèmes de gestion mémoire ne seront pas détectés. Il peut cependant vous signaler des free multiples.
- Sa facilité d'emploi devrait toutefois inciter tout codeur un tant soit peu consciencieux à l'utiliser.
- Une alternative consiste à laisser tomber
mallocetfree, mais je laisse ça aux gens qui ont des problèmes de mémoire.