Bonjour,
Peut-etre qu'ici quelqu'un connaitrait un trackeur de fuites mémoires pour programme C sous Mac Os X ???
Merci, et bonne journée à tous !
Version imprimable
Bonjour,
Peut-etre qu'ici quelqu'un connaitrait un trackeur de fuites mémoires pour programme C sous Mac Os X ???
Merci, et bonne journée à tous !
Pas sûr que ça fonctionne sous Mac OS X, mais les plus connus sont Valgrind, Purify, efence. Il y a aussi ma modeste contribution :Citation:
Envoyé par Fabllot
http://emmanuel-delahaye.developpez.com/clib.htm
Module SYSALLOC
qui a l'avantage d'être 100% ANSI donc indépendante de la plateforme...
D'après leurs docs Valgrind, Purify et efence ne sont pas prévus pour Mac Os X, je me suis donc retourné vers ta bibliothèque.
(Au passage, les indications sur ton site sont très claires, et tout fonctionne bien très vite !)
Dans mon programme en C, j'interface une bibliothèque en C++, et j'ai peur que les fuites mémoires viennent de là...
Est-ce que ta bibliothèque peut alors fonctionner pour voir si mes structures C, utilisées dans ce fichier C++, et initialisées avec des "malloc", sont bien libérées (ce fichier est le seul du projet compiler avec g++) ?
D'autres part, je manipule pas mal de chaîne de caractères, parfois ces chaînes de caractères sont initialisés automatiquement avec des malloc mais parfois ce sont des constantes (je sais c'est pas terrible) alors cela pose certains problèmes pour la libération de la mémoire... Y'a t-il un moyen "propre" de procéder ?
C'est pas très clair. Le programme est en C et il appelle des fonctions C++ ou le contraire ?Citation:
Envoyé par Fabllot
Mon code est prévu pour un programme compilé en C. Il ne traite pas les new/delete du C++. Cependant, son interface (sysalloc.h) est prévue pour fonctionner dans un environnement C++ (jamais testé) du moment que son implémentation (sysalloc.c) est compilée en C, on est bien d'accord ?
OK, oui. Mais ton code C devrait être indépendant du C++ et donc être testable séparément en tant qu'application C.Citation:
Est-ce que ta bibliothèque peut alors fonctionner pour voir si mes structures C, utilisées dans ce fichier C++, et initialisées avec des "malloc", sont bien libérées (ce fichier est le seul du projet compiler avec g++) ?
Oui.Citation:
D'autres part, je manipule pas mal de chaîne de caractères, parfois ces chaînes de caractères sont initialisés automatiquement avec des malloc mais parfois ce sont des constantes (je sais c'est pas terrible) alors cela pose certains problèmes pour la libération de la mémoire... Y'a t-il un moyen "propre" de procéder ?
Déjà, libérer une chaine non allouée est un bug grave. (comportement indéterminé).
Le plus simple est d'utiliser exclusivement l'allocation dynamique et la libération est systématique (remets à NULL après libération, ça évite les embrouilles)
Si tu as une chaine constante, tu fais une copie dynamique avec la fonction POSIX.1 strdup(). Attention, elle échappe à la surveillance de SYSALLOC.Code:free (p), p = NULL;
Pour éviter ça, j'utilise ma fonction STR_dup() du module STR qui a l'avantage d'être portable (100% C-ANSI).
N'hésite pas à poser des questions si nécessaire.
Fait des essais sur des petits bouts de code pour t'entrainer à maitriser SYSALLOC.
Pour les chaines, une alternative est d'apprendre à utiliser mon module FSTR (Flexible STRings). Si besoin est, je fais une doc (il y a déjà le test unitaire qui sert d'exemple... si on arrive à le comprendre).
Le programme principale est C, et appelle des fonctions écrites en C++ ayant des signatures C.Citation:
Envoyé par Emmanuel Delahaye
Je te remercie pour ces conseils. Cependant, je ne vais utiliser tes bibliothèques que pour tester les miennes... Il pourrait y avoir quelques problèmes de licences et de droits d'auteurs sinon...Citation:
Envoyé par Emmanuel Delahaye
On va considérer que c'est du C. Les fonctions de cette bibliothèque sont, bien sûr, validées et ne créent pas de fuite mémoire quand elles sont bien utilisées, on est d'accord ?Citation:
Envoyé par Fabllot
Mon code est libre de droit. Je demande juste que le nom de l'auteur (ED) soit laissé. C'est pas trop méchant comme licence...Citation:
Je te remercie pour ces conseils. Cependant, je ne vais utiliser tes bibliothèques que pour tester les miennes... Il pourrait y avoir quelques problèmes de licences et de droits d'auteurs sinon...
Après avoir éliminer toutes les fuites mémoires de ma bibliothèque codée en C (pas une mince affaire), je me suis attaquée à mon interface de bibliothèque c++.
En fait, cette interface est codée en C++, avec des classes C++ (comportant des attributs et des méthodes) et compilée avec g++. Mais cette interface posséde aussi quelques fonctions avec des entêtes C, qui sont appelées depuis la partie de la bibliothèque codée en C.
J'ai donc tester ta bibliothèque SYS_ALLOC sur cette interface, mais a priori ne fonctionne pas. J'ai tester en rajoutant des lignes comme
sans mettre de "free", bien sûr! Et au final, aucune fuite mémoire n'est détectée, quelle que soit l'endroit où est rajouté le malloc...Code:
1
2 int* testMalloc = (int*) malloc (sizeof (int) * 10);
Est-ce que tu as mis #include "ed/inc/sysalloc.h" a la première ligne le source qui contient ce malloc () ?Citation:
Envoyé par Fabllot
Oui...
Et même quand g++ est appelé, DBG_SYSALLOC est définie globalement sur la ligne de commande ?Citation:
Envoyé par Fabllot
Oups... :oops:Citation:
Envoyé par Emmanuel Delahaye
Bon effectivement, les malloc bidons sont reconnus, et je n'avait pas d'autres fuites mémoire avec des mallocs sur cette interface C++...
Toujours est-il qu'il me reste quelques soucis.
En fait ce sont des fuites mémoires minimes : on ne les voit pas en execution normale, en regardant la mémoire utilisée par mon programme.
Le soucis, c'est que je doit prouver une certaine fiabilité de mon programme en le bombardant. Du coup, je n'appelle pas les fonctions "percées" quelques fois ou même centaine de fois, mais plutôt quelques centaines de milliers de fois voire millions de fois...
Alors, là les soucis arrivent... Comme on dit, ce sont les petits ruisseaux qui forment les grandes rivières, et bien imaginez ce que cela donne, avec des millions de ruisseaux !!!
Je ne vois donc pour le moment qu'une solution (outre colmater les fuites -- mais mon temps est compté), c'est de créer un shell qui lancera pleins de fois mon programme...
D'où une petite question, pour un programme lancer par un shell, la libération de la mémoire utilisée par le programme se fait à la fin de l'execution de celui-ci ou à la fin du shell ?
En théorie, à la fin du programme, ou sous unixoïde, peut-être bien au moment où le shell détecte la fin du programme.
De quelles fuites s'agit-il et comment sont elles évaluées ?Citation:
Envoyé par Fabllot
Ca ne va rien changer. Ou alors, c'est que le système est sérieusement buggé (ne récupère pas la mémoire libérée) ou que c'est une autre ressource que 'malloc/free' qui est en jeu.Citation:
Je ne vois donc pour le moment qu'une solution (outre colmater les fuites -- mais mon temps est compté), c'est de créer un shell qui lancera pleins de fois mon programme...
Attention à ne pas se tromper de cible. C'est ton code que tu testes, pas le système. Si ton code provoque des fuites mémoire dans le système, il faut chercher ailleurs...
Pour tester la stabilité du programme dans le temps, tu peux ajouter un mécanisme (commande shell, timer, clickodrome) qui appelle la fonction sys_mem_trace() et/ou sys_mem_counters() qui indique l'état courant de la mémoire sur stdout. Ca permet de vérifier la stabilité de la mémoire en allant consulter de temps en temps dans les phases de calme.
C'est comme ça que j'ai qualifié des équipements de réseau numériques 24/7. Ils tournent toujours...
Si je le savais... "Evaluées" est un bien grand mot. Normalement à chaque appelle d'une fonction F je créé dans cette fonction un certains nombre d'objets puis je les libère...Citation:
Envoyé par Emmanuel Delahaye
Je devrais donc pouvoir appeller une infinité de fois cette fonction sans que cela pose de problème. Seulement, au bout de 50.000 à 100.000 appels, le systèmes s'écroule (tout la mémoire physique et virtuelle est utilisée !)
J'en déduis donc qu'il y a des fuites mémoires (qui peuvent hélas venir d'une bibliothèque que j'utilise...)
Comme cette partie du code est en C++ je pencherais donc pour des 'new/delete' qui sont appelés automatiquement par la bibliothèque externeCitation:
Ca ne va rien changer. Ou alors, c'est que le système est sérieusement buggé (ne récupère pas la mémoire libérée) ou que c'est une autre ressource que 'malloc/free' qui est en jeu.
C'est pas vraiment la stabilité que je recherche (un peu tout de même) mais plutôt la fiabilité et la jutesse des résultats retournés. En fait, la fonction que je teste est un solveur de contraintes, et je veux être certain qu'il me résouds correctement mes systèmes de contraintes...Citation:
Pour tester la stabilité du programme dans le temps, [...]
J'ai tout de même créé un script Unix qui appelle mon application par "partie", et cela à l'air de fonctionner...
OKCitation:
Envoyé par Fabllot
OK, si les fonctions utilisées pour gérer la mémoire sont standards : malloc()/free() pour les parties C et new/delete pour les parties C++. Au fait en C++ (que je connais très mal), il y a de sales gags entre delete et delete[]. C'est bien clair tout ça au contrôle visuel ?Citation:
Je devrais donc pouvoir appeller une infinité de fois cette fonction sans que cela pose de problème.
Et les appels systèmes directes genre mmap() et autres réservations de mémoire shm_xxx() etc. c'est clair ? Y'a plein de code qui échappe à malloc()/free().
Et les flux ? Ils sont bien refermés dans tout les cas, même en cas d'erreur ? Il y a tellement de cas possibles. Il faudrait expertiser ton code. Et les drivers (open()/close() ?...
C'est un message du système ?Citation:
Seulement, au bout de 50.000 à 100.000 appels, le systèmes s'écroule (tout la mémoire physique et virtuelle est utilisée !)
C'est possible, mais il y a d'innombrables causes...Citation:
J'en déduis donc qu'il y a des fuites mémoires (qui peuvent hélas venir d'une bibliothèque que j'utilise...)
Et une fois que tu as quitté le programme, la mémoire revient ?
Dans la réalité, tu vas réellement faire 100.000 appels avant de quitter le programme ?
Tu testes par blocs fonctionnels autonomes. Bonne conception et bonne méthode. C'est bien.Citation:
J'ai tout de même créé un script Unix qui appelle mon application par "partie", et cela à l'air de fonctionner...
C'est clair, rien à dire...Citation:
Envoyé par Emmanuel Delahaye
J'en utilise pas... Je me limite juste au delete et new et sans même et sans tableau (donc pas de delete[])Citation:
Et les appels systèmes directes genre mmap() et autres réservations de mémoire shm_xxx() etc. c'est clair ? Y'a plein de code qui échappe à malloc()/free().
Y'a pas de gestion de flux dans cette partie du code, donc pas de problème normalement de ce coté, idem au niveau de la gestion des chaines de caracteres (j'en ai parlé précédemment) : elle ne sont pas utilisées dans cette partie du programme...Citation:
Et les flux ? Ils sont bien refermés dans tout les cas, même en cas d'erreur ? Il y a tellement de cas possibles. Il faudrait expertiser ton code. Et les drivers (open()/close() ?...
Non, c'est moi qui le déduit... J'ai pas mal de compteur qui observe ce qui se passe...Citation:
Seulement, au bout de 50.000 à 100.000 appels, le systèmes s'écroule (tout la mémoire physique et virtuelle est utilisée !)
C'est un message du système ?
Oui, la mémoire revient aussitôt.Citation:
Et une fois que tu as quitté le programme, la mémoire revient ?
Dans la réalité, pour un usage normal : non. C'est juste pour tester mon programme. Après, ma biliothèque est réutilisée pour autre chose, là je ne garantie rien...Citation:
Dans la réalité, tu vas réellement faire 100.000 appels avant de quitter le programme ?
Merci.:DCitation:
Tu testes par blocs fonctionnels autonomes. Bonne conception et bonne méthode. C'est bien.
Pas de chaines de caractères, donc. OK. Au cas où, je ne sais plus si on a évoqué strdup(), là aussi c'est clair ? Il y a bien un free() pour chaque ?Citation:
Envoyé par Fabllot
Ah, est-tu bien sûr de ton instrument de mesure. C'est le B.A. BA. Rien de pire qu'un fausse alarme !Citation:
Non, c'est moi qui le déduit... J'ai pas mal de compteur qui observe ce qui se passe...
OK. C'est donc bien de la mémoire 'C' (ou C++) qui est sur-consommée.Citation:
Oui, la mémoire revient aussitôt.
Bon, je crois que j'ai résolu tous mes problèmes de fuites de mémoires... Aussi bien dans le code C que dans le C++...
Merci à tous pour votre aide et vos remarques.
C'est un peu tard pour t'aider, mais c'est bon à savoir :
Il y a un tracker de mémoire C++ (pour les new/delete) dans le premier chapitre de ces tutoriaux :Conception d'un moteur 3D