7
votes

Est-ce une fuite de mémoire pour pousser_back un pointeur dans un vecteur de pointeurs?

Dans ma classe, j'ai une variable de membre std :: vecteur enfants

Est-ce que la fonction de membre de la classe suivante crée une fuite de mémoire? xxx

Le vecteur fait une copie du pointeur et j'ai deux pointeurs à la même mémoire, Et puis le pointeur d'origine est hors de portée, non?

Ceci peut être simple et évident, mais je voudrais juste confirmer mon hypothèse.
merci


5 Réponses :


2
votes

Ce n'est qu'une fuite de mémoire si vous oubliez de rétrograder le nœud enfants lorsque la classe contenant le destructeur du vecteur est appelée.


1 commentaires

super! Je vous remercie. Ouais, mon destructeur boucle à travers le vecteur et supprime chaque pointeur. Je ne trouve aucune raison de les mettre à NULL car les pointeurs disparaîtront bientôt.



1
votes

Ce n'est pas une fuite de mémoire. Vous avez toujours un pointeur dans le vecteur et vous pourrez libérer la mémoire si nécessaire.


0 commentaires

1
votes

Lorsque le vecteur sort hors de portée, il est destructeur ne détruit pas l'objet pointu à l'objet. Il détruit le pointeur - ce qui ne fait rien.

Votre code a créé cet objet via Nouveau . Votre code est responsable de la suppression de cet objet. Si vous ne le faites pas, vous avez une fuite. Si vous le faites pour tôt, c'est-à-dire avant de retirer le pointeur du vecteur, vous avez encore plus de problèmes.


0 commentaires

-3
votes

supposer enfants code> est un membre de classe que vous seriez simplement supprimer tous les éléments du vecteur sur le déconstructeur de classe.

struct Foo{};

class Bar
{
public:
    Bar(){};
    ~Bar()
    {
        for( vector<Foo*>::iterator it = children.begin(); it != children.end(); ++it )
        {
            SAFE_DELETE( (*it) ); //use your own macro/template or use delete if you don't have one
            delete (*it);
            (*it) = NULL;
        }
    }
    vector<Foo*>children;
}

Foo* p = new Foo();
children.push_back( p );


11 commentaires

Ça a du sens. Je ne pense pas que j'ai besoin de les mettre à NULL, car l'objet entier sera détruit. Je ne comprends pas le but de la macro / modèle.


Je n'ai pas bien compris, vous ne pensez pas que vous devez définir un pointeur sur NULL lorsque vous le supprimez ?. Safe_Delete a été un macro / modèle connu pour les âges, il est à but de supprimer en toute sécurité un élément alloué en tas. Je vous recommande de lire efficacement / plus efficace C ++ de David Mayhew et Scott Meyers.


Je ne suis pas le descendant, mais c'est idiot. Safe_Delete n'est pas sûr; Tout ce qu'il fait, c'est vérifier si le pointeur est null avant d'appeler Suppr . Il n'y a rien de mal à supprimer un pointeur nul. Il n'y a pas besoin de ce test; Il n'y a pas besoin d'utiliser Safe_Delete au lieu d'utiliser simplement Supprimer . Pour faire Safe_Delete Vraiment sûr, il faudrait vérifier en quelque sorte si un pointeur non nul a été attribué vraiment avec nouveau avant d'appeler Supprimer . Ça ne fait pas ça. Il n'y a pas non plus de raison de définir le pointeur sur null après l'avoir supprimé; Nous sommes dans le destructeur.


Je pourrais écrire au moins 2 exemples où Safe_Delete Outtus un simple Supprimer appel. Définition d'un pointeur sur 0 (qui est "NULL" en standard C ++, la null définie de C est quelque peu différente) évite les accidents de la double suppression. Il existe de nombreuses possibilités, le pointeur pourrait être partagé, avoir des références. Si vous dites "hé, il n'y a rien de mal à ne pas régler les pointeurs à NULL après que je les ai supprimés, j'ai vu beaucoup d'autres programmeurs le faire et leur programme fonctionne bien"


est la même chose que "AW, la sécurité de cette arme à feu est une douleur à régler tout le temps. Et de toute façon, d'autres personnes ne l'utilisent pas non plus, et certaines d'entre elles n'ont pas tiré leurs propres pieds ...". Au moins dans mon environnement, avec des applications de serveur / client multithreaded, exécutant la même partie d'un code par seconde par seconde. Les pratiques de sécurité sont les minimales


Le problème est que Safe_Delete n'est ni sûr ni nécessaire. Maintenant, je suis l'un des descendants.


Si tel est votre d'opinion , ok


Si vous devez définir des pointeurs sur NULL dans le destructeur des objets qui leur possèdent afin d'éviter les doubles suppressions, vous avez de plus gros problèmes. Fondamentalement, vos objets n'ont pas une durée de vie ou une propriété bien définie, et au lieu de guérir cela, vous cachez les symptômes. (Et quelqu'un a-t-il mentionné que cette classe viole la règle de trois?)


Il s'agit d'un petit exemple pour répondre à la question connexe, si vous souhaitez appliquer votre narcissisme sceptique à parler de la règle de trois sur un Vecteur , fuite de mémoire Question Petite pièce de code exemple Je suis sûr que vous êtes tout à fait un erudite WG21. Je suis d'accord avec votre point sur la définition de la vie des objets, mais tous les codes ne sont pas réduits à cet exemple. Le tas n'est pas sympathique, je préfère définir des pointeurs à NULL au lieu de traiter de la mémoire obscure débogage plus tard.


Comment quelqu'un pourrait-il aussi citer la règle de trois lorsqu'il s'agit d'une fuite de mémoire? Cette chose qui traite des fuites de mémoire .. contre une fuite de mémoire? TVA IZ ZIS


Chaque fois que vous dites Supprimer dans votre code, vous le faites mal.



13
votes

Ce n'est pas une fuite ... encore. Toutefois, si le est hors de portée ou que vous efface , pop_back ou faites quelque chose d'autre qui supprime des éléments du vecteur, sans premier < code> Supprimer L'élément que vous avez enlevé, vous aurez une fuite sur vos mains.

La bonne façon de le faire est de passer de l'utilisation d'un vecteur to vecteur > . Votre code passera à xxx

ou utiliser boost :: ptr_vector si vous pouvez utiliser boost.


2 commentaires

Ouais, je pourrais éviter les pointeurs cru, mais je n'aurais pas la pratique de suivre des fuites de mémoire! :) Je ne savais pas que Boost avait une classe comme ça! Merci


La dernière ligne peut simplement être enfants.emplace_back (enfant);