45 votes

Fuite de mémoire C++

Je viens d'écrire un code en C++ qui fait un peu de manipulation de chaînes de caractères, mais quand j'ai lancé valgrind dessus, il montre des fuites de mémoire possibles. En déboguant le code à un niveau granulaire, j'ai écrit un programme simple en C++ qui ressemble à ceci :

#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
        std::string myname("Is there any leaks");
        exit(0);
}

et en faisant tourner Valgrind dessus, j'ai obtenu.. :

==20943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 26 from 1)
==20943== malloc/free: in use at exit: 360,645 bytes in 12,854 blocks.
==20943== malloc/free: 65,451 allocs, 52,597 frees, 2,186,968 bytes allocated.
==20943== For counts of detected errors, rerun with: -v
==20943== searching for pointers to 12,854 not-freed blocks.
==20943== checked 424,628 bytes.
==20943== 
==20943== LEAK SUMMARY:
==20943==    definitely lost: 0 bytes in 0 blocks.
==20943==      possibly lost: 917 bytes in 6 blocks.
==20943==    still reachable: 359,728 bytes in 12,848 blocks.
==20943==         suppressed: 0 bytes in 0 blocks.
==20943== Reachable blocks (those to which a pointer was found) are not shown.
==20943== To see them, rerun with: --show-reachable=yes

Je me suis alors rendu compte que nous avions forcé la sortie (ce que j'avais fait dans mon code C++ original). Maintenant le problème est que je veux sortir du programme alors que mon ancien code attend le statut de sortie du nouveau code. Par exemple, le binaire a.out attend l'état de sortie de b.out. Y a-t-il un moyen d'éviter les fuites de mémoire, ou dois-je vraiment m'inquiéter des fuites de mémoire puisque le programme est déjà en train de se terminer à ce moment-là ?

Cela soulève également une autre question pour moi : un tel code est-il nuisible ?

#include<stdio.h>
#include<cstdlib>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}

65voto

swegi Points 3074

Utilisez return 0; au lieu de exit(0); à la fin de main . L'utilisation de exit contourne l'exécution des destructeurs.

63voto

SigTerm Points 16055

Si usted insister sur l'utilisation exit() :

#include<iostream>
int main(){
    {
        std::string myname("Are there any leaks?");
    }
    exit(0);
}

Aussi, quand vous revenez de main la valeur renvoyée devient le code de sortie de l'application. Donc, si vous voulez passer un code de sortie, utilisez return exitCode; en main() au lieu de exit .

En ce qui concerne cette partie :

Cela soulève également une autre question pour moi : un tel code est-il nuisible ?

Oui, parce que c'est un MAUVAIS habitude de programmation.

Le système d'exploitation nettoiera toute la mémoire que vous n'avez pas libérée, donc tant que vous n'avez pas réussi à manger toute la mémoire système et le fichier page, vous ne devriez pas endommager le système d'exploitation.

Cependant, l'écriture d'un code peu soigné ou peu fiable peut devenir une habitude, et compter sur le système d'exploitation pour réparer les dégâts est une mauvaise idée.

22voto

sbi Points 100828

Cela soulève également une autre question pour moi : un tel code est-il nuisible ?

#include<stdio.h>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}

Ce n'est pas dangereux sur les systèmes d'exploitation modernes, car ils ferment automatiquement toutes les ressources appartenant à un processus lorsque celui-ci se termine.

Cependant, cela reste une mauvaise pratique et peut conduire à des erreurs subtiles et difficiles à trouver lorsque, sur plusieurs années de maintenance, le code change lentement jusqu'à ce que, un jour, cela devienne nuisible. J'ai travaillé sur des projets dont une partie du code avait une dizaine d'années et j'en ai tiré quelques leçons, parfois assez dures. Par conséquent, j'éviterais d'écrire un tel code, même s'il ne pose pas de problème actuellement.

5voto

Rob Points 1138

Dans la plupart des cas, cela vaut la peine de faire le ménage soi-même, pour les nombreuses bonnes raisons déjà évoquées : meilleure maintenabilité, meilleure utilité des outils de vérification, etc.

S'il y a d'autres raisons fonctionnelles de faire le ménage, par exemple si vos données sont sauvegardées dans une mémoire persistante, vous n'avez pas le choix : vous devez faire le ménage (même si vous devriez peut-être revoir votre conception).

Dans certains cas cependant, il peut être préférable de sortir et de "fuir".

À la fin d'un programme, votre processus va se terminer. Lorsqu'il le fait, le système d'exploitation récupère toute la mémoire allouée par votre programme et, dans certains cas, il peut le faire beaucoup plus rapidement.

Considérons une grande liste liée, où chaque nœud est alloué dynamiquement, et porte une structure importante allouée dynamiquement. Pour nettoyer tout cela, vous devez visiter chaque nœud et libérer chaque charge utile (ce qui peut à son tour entraîner le déplacement d'autres structures complexes).

Vous pouvez finir par effectuer des millions d'opérations de mémoire pour parcourir une telle structure.

L'utilisateur veut quitter votre programme, et il reste là pendant des dizaines de secondes à attendre qu'un tas de traitements inutiles se produisent. Il ne peut pas être intéressé par le résultat - il quitte le programme après tout.

Si vous laissez cette "fuite", le système d'exploitation peut récupérer beaucoup plus rapidement l'intégralité du bloc de mémoire alloué à votre processus. Il ne se soucie pas des structures et du nettoyage des objets.

http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

En fin de compte, vous devez comprendre ce que vos outils vous disent, pour être sûr de les utiliser correctement.

4voto

Mike Seymour Points 130519

Pour éviter les fuites de mémoire, renvoyer l'état à partir de main au lieu d'appeler exit . Si vous renvoyez un résultat nul, vous pouvez omettre l'élément return si vous le souhaitez ; le programme se terminera avec un statut de zéro dans ce cas.

Cela soulève également une autre question pour moi : un tel code est-il nuisible ?

Sur un système d'exploitation moderne, cela ne causera aucun dommage - toutes les ressources sont récupérées automatiquement lorsqu'un programme se termine. Cependant, il est plus difficile d'utiliser des outils comme Valgrind pour trouver de véritables problèmes. Il est donc préférable d'éviter les fuites de mémoire, même inoffensives, si vous le pouvez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X