7
votes

Fuite de mémoire - Ensembles STL

J'essaie de brancher toutes mes fuites de mémoire (qui est massive). Je suis nouveau à STL. J'ai une bibliothèque de classe où j'ai 3 ensembles. Je crée également beaucoup de mémoire avec NOUVEAU dans la classe de bibliothèque pour ajouter des informations aux ensembles ...

Dois-je avoir besoin de rétrograder les ensembles? Si oui, comment? P>

Voici la bibliothèque.h p> xxx pré>

Je ne suis pas sûr de ce que je dois faire pour le destructeur? P>

    const Item* Library::addBook(const string& title, const string& author, const int nPages)
{

    ItemSet* obj = new ItemSet();
    Book* item = new Book(title,author,nPages);
    allBooks.insert(item); // add to set of all books
    obj->insert(item);


8 commentaires

Réponse courte: recherchez chaque instance du caractère * dans votre code et supprimez-le. Vous n'avez guère besoin d'utiliser des pointeurs en C ++. Chaque fois que vous faites, vous demandez des fuites de mémoire.


Il y a beaucoup de fois que vous devez utiliser des pointeurs en C ++, même si vous utilisez des types standard.


Dans ce cas, élément est une classe de base pour les objets stockés, vous devez donc stocker des pointeurs dans itemset et itemmap . Stocker les pointeurs intelligents réparera ces fuites. itemseetMap doit simplement contenir des objets définis.


Oui, il y a des exceptions, mais avez-vous même regardé le code de l'OP? Il utilise des pointeurs pour tous les . Pointeurs de magasin de conteneurs, chaque objet est référencé par des pointeurs, tout est alloué de manière dynamique, tout doit être nettoyé. Sérieusement me dis-tu que c'est "paranoïa" de lui dire qu'il ne devrait pas utiliser les pointeurs pour toutes ces choses?


@ Steve314: Ce ne sont pas des problèmes "possibles", ce sont de vrais problèmes. Vous ne pouvez pas modifier sensiblement le code de nettoyage aux destructeurs des conteneurs standard et, même si vous le faites, il y aura toujours des fuites lorsque vous supprimez ou écrasez des objets dans le conteneur. Fixer des fuites de mémoire n'est ni paranoïaque ni sacrée; Cela fait partie du logiciel qui fonctionne.


Mes commentaires passés ont supprimé non pas aussi incorrect, mais aussi excessif et inapproprié ici.


En fait, je ne vois pas comment vous pouvez avoir de manière significative un définir <élément *> en premier lieu. Vous ne pouvez pas surcharger opérateur << / code> pour deux types de pointeur, par conséquent, l'ensemble serait commandé par adresses, et vous ne pourrez donc pas rechercher quoi que ce soit dans l'ensemble (sans itération linéairement) sauf si Vous avez déjà ce pointeur stocké ailleurs. (Ce qui signifierait que vous avez déjà l'objet que vous vouliez rechercher.)


Je crois comprendre que l'utilisation des pointeurs intelligents dans des classes de conteneurs peut être dangereuse. Si le conteneur doit déplacer les objets, des problèmes peuvent survenir. Stackoverflow.com/questions/4577838/... < / a>


7 Réponses :


1
votes

ne sont pas passés par votre code mais à partir des premières lignes, il semble que vous conserviez des ensembles de pointeurs. Chaque fois que vous avez un conteneur STL qui contient des pointeurs et que vous utilisez neuf pour mettre des trucs dans les pointeurs, vous devez utiliser Supprimer pour annouez ces pointeurs. STL ne fait pas ça pour vous. En fait, STL ne sait même pas qu'ils sont des pointeurs.

Une autre option consiste à ne pas utiliser de pointeurs du tout et d'avoir un ensemble de juste les objets et non d'utiliser nouveau pour les créer. Il suffit de les créer sur la pile et de les copier dans l'ensemble.


0 commentaires

0
votes

Dans le destructeur, vous devez itérer sur vos collections STL contenant des pointeurs et les supprimer. Comme ceci: xxx


0 commentaires

3
votes

Vous devez libérer la mémoire de chaque élément de l'ensemble. Le conteneur ne fera pas cela pour vous, et cela ne devrait pas savoir car il ne peut pas savoir si cela détient cette propriété ou non - il pouvait simplement organiser des pointeurs vers des objets appartenant à autre chose.

Ceci est un générique gratuit. fonction qui comportera tout conteneur STL. xxx


4 commentaires

Mais vous avez besoin de RTTI pour ça, hah!


Pourquoi auriez-vous besoin de RTTI pour cela?


Il a probablement besoin des classes pour avoir des destructeurs virtuels. La plupart des classes ont besoin de destructeurs virtuels de toute façon. Le problème est une propriété de la classe, et non de cette fonction DealLocate_Container, iow. Un problème, cependant, fonctionne-t-il pour STD :: Carte, qui a la clé et des données pour chaque article, soit à la fois potentiellement un pointeur?


Oui, cela nécessite un destructeur virtuel, mais c'est orthogonal à l'utilisation de cette fonction. Et oui, cela ne fonctionnera pas avec des cartes car les itérateurs pointent vers des paires. Pour les cartes, vous pouvez avoir une mémoire allouée de manière dynamique dans la clé et / ou la valeur, de sorte que vous auriez besoin d'écrire des versions pour celles spécialement.



1
votes

Eh bien, cela pourrait être un commentaire stupide, mais avez-vous vraiment besoin de faire allouer tous vos trucs - alloués à tous vos trucs (AKA. Utiliser des pointeurs et du nouveau?)

Vous ne pouvez pas simplement utiliser des instances simples? Raii permet de faciliter le code et aucune fuite de mémoire.

par exemple a: xxx

avec cette approche, le destructeur doit faire strictement rien, et pas de mémoire fuir. Dans la plupart des cas, l'utilisation des pointeurs peut être facilement évitée et devrait définitivement!


0 commentaires

0
votes

Comme d'autres l'ont noté, vous devez annoncer les indicateurs. Le «code> définir Destructor ne ferait normalement pas cela pour vous. Sinon, si vous voulez que cela soit fait pour vous, utilisez un boost :: scoped_ptr ou un std_ptr où vous pouvez spécifier un Delier personnalisé à faire ce travail pour vous.


0 commentaires

4
votes

Les conteneurs STL ne sont pas conçus pour contenir des pointeurs.

Regardez les conteneurs de pointeur Boost. Ces conteneurs sont conçus pour contenir des pointeurs. P> xxx pré>

http://www.boost.org/doc/libs/1_42_0/libs/ptr_container/doc/ptr_set.html P>

Les conteneurs tiennent et posséder les pointeurs afin qu'ils soient supprimés lorsque le conteneur est hors de portée. Mais la belle chose à propos des conteneurs est que vous accédez aux objets via des références afin que tous les algorithmes standard fonctionnent sans adaptateurs spéciaux. P>

typedef boost::ptr_set<Item>              ItemSet;
typedef boost::ptr_map<string,Item>       ItemMap;
typedef boost::ptr_map<string,ItemSet>    ItemSetMap;


0 commentaires

1
votes

En regardant une partie du code que vous avez posté dans d'autres questions (telles que https: // Stackoverflow .Com / Questions / 2376099 / C-Add-to-Stl-Set ), vos articles sont stockés dans plusieurs objets globaux code> objets code>. Ce n'est pas un bon design - ils devraient vraiment faire partie de l'objet de la bibliothèque code> code>, car ils appartiennent logiquement à cela.

Le meilleur moyen de résoudre les fuites de mémoire ne doit pas traiter les pointeurs bruts - Soit stocker des pointeurs intelligents dans les ensembles ou utiliser des conteneurs de pointeur Boost comme Martin York suggère. De plus, vos objets itemseTeTmap code> doivent contenir définir des objets code> plutôt que des pointeurs - il n'y a absolument aucune raison de stocker des pointeurs d'origine. p>

Si vous devez vraiment stocker des pointeurs, votre destructeur doit passer à travers chaque ensemble pour supprimer le contenu: P>

void Purge(ItemSet &set)
{
    for (ItemSet::iterator it = set.begin(); it != set.end(); ++it)
        delete *it;
    set.clear(); // since we won't actually be destroying the container
}

void Purge(ItemSetMap &map)
{
    for (ItemSetMap::iterator it = map.begin(); it != map.end(); ++it)
        delete it->second;
    map.clear();
}

Library::~Library()
{
    Purge(allBooks);
    Purge(allCDs);
    // and so on and so forth
}


3 commentaires

J'ai aussi un ensemble Typedef Stringset; Stringset * Movieciast; Puis-je simplement utiliser Supprimer Movieciast dessus? Ou dois-je faire itération?


Non, vous n'avez pas à itérer un Set , car cela contient des objets et les interdisera eux-mêmes. Vous n'avez besoin que de supprimer des objets que vous avez alloués à l'aide de Nouveau et vous devez éviter de le faire quand vous le pouvez.


J'ai utilisé de nouvelles pour ajouter des informations à mes séries dans presque toutes mes fonctions telles que: itemset * obj = nouvel itemset (); Comment puis-je supprimer ceux-ci? Je ne peux pas les supprimer avant de quitter la fonction. - J'espère que Oyu ne me dérange pas mais j'ai utilisé vos fonctions de purge.