web-dev-qa-db-fra.com

Détecter les fuites de mémoire dans les programmes C?

Si nous voulons vérifier les fuites de mémoire dans un programme C++, nous pouvons surcharger les opérateurs new et delete pour garder une trace de la mémoire allouée. Et si nous voulions vérifier les fuites dans un programme C? Puisqu'il n'y a pas de surcharge d'opérateur en C, pouvons-nous écraser le pointeur de fonction malloc pour intercepter les appels à malloc et suivre l'allocation de mémoire? Existe-t-il un moyen plus simple sans utiliser d'utilitaires externes? Veuillez fournir du code car je ne suis pas familier avec les pointeurs de méthode de remplacement.

Remarque: je voudrais le faire sans utilitaires externes pour la pratique.

24
Mike G

Comme suggéré, il existe déjà d'excellents outils comme Valgrind pour ce faire.

Plus loin:

je voudrais le faire sans utilitaires externes pour la pratique
C'est intéressant et je suis sûr que ce serait satisfaisant,
Vous pouvez utiliser une macro pour détecter une telle utilisation de la mémoire et des erreurs de fuite, en fait, écrivez votre propre détecteur de fuite. Vous devriez pouvoir le faire tant que vous avez une seule fonction d'allocation et de désallocation dans votre projet.

#define malloc(X) my_malloc( X, __FILE__, __LINE__, __FUNCTION__)

void* my_malloc(size_t size, const char *file, int line, const char *func)
{

    void *p = malloc(size);
    printf ("Allocated = %s, %i, %s, %p[%li]\n", file, line, func, p, size);

    /*Link List functionality goes in here*/

    return p;
}

Vous conservez une liste liée d'adresses allouées avec le fichier et le numéro de ligne d'où ils ont été alloués. Vous mettez à jour la liste des liens avec des entrées dans votre malloc.

Comme ci-dessus, vous pouvez écrire une implémentation pour free, dans laquelle vous vérifiez les entrées d'adresse qui doivent être libérées par rapport à votre liste chaînée. S'il n'y a pas d'entrée correspondante, c'est une erreur d'utilisation et vous pouvez la signaler ainsi.

À la fin de votre programme, vous imprimez ou écrivez le contenu de votre liste chaînée dans un fichier journal. S'il n'y a pas de fuites, votre liste chaînée ne devrait pas avoir d'entrées mais s'il y a des fuites, le fichier journal vous donne l'emplacement exact de l'endroit où la mémoire a été allouée.

Notez qu'en utilisant cette macro, vous perdez le type de vérification des fonctions proposées mais c'est une petite astuce que j'utilise beaucoup de fois.

J'espère que cela vous aide et tout le meilleur :)

45
Alok Save

Valgrind est ce dont vous avez besoin.

Je me souviens avoir lu le premier chapitre de Algorithms in a Nutshell qui en parlait bien qu'il n'inclue pas de code. Juste ajouté au cas où vous le trouveriez intéressant.

comme il n'y a pas de surcharge d'opérateur en c, pouvons-nous écraser la fonction malloc pour intercepter les appels à malloc et suivre l'allocation de mémoire

En fait, vous le pouvez. DONNEZ LD_PRELOAD une lecture.

13
Abhijeet Rastogi

En plus de la réponse de @ Als qui encapsulera les appels dans votre code source, si vous utilisez gnu ld, vous pouvez demander à l'éditeur de liens d'envelopper tous les appels (vraisemblablement à malloc, realloc, calloc et free) au moment de la liaison, quelle que soit leur origine. Vous écrivez ensuite __wrap_malloc etc et peut appeler la fonction d'origine avec, par exemple, __real_malloc.

Voir --wrap=symbol dans http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html

Je ne sais pas comment cela fonctionne avec les appels des bibliothèques partagées. Je suppose que non.

5
smparkes

Utilisez la fonction mallinfo, cela a fonctionné pour moi sur le baremetal Xilinx Zynq en utilisant Xilinx SDK gcc. J'ai testé avec une fuite de mémoire intentionnelle - je ne sais pas pourquoi, mais les résultats de Google sont incroyablement terribles à trouver cette solution pour répandre le mot pour aider d'autres développeurs!

2
Mister Pidot

Voici comment vous pouvez modifier malloc, hooks gratuits: Hooks for Malloc

1
TJP