web-dev-qa-db-fra.com

Suppression d'un objet en C ++

Voici un exemple de code que j'ai:

void test()
{
   Object1 *obj = new Object1();
   .
   .
   .
   delete obj;
}

Je l'exécute dans Visual Studio et il se bloque à la ligne avec 'delete obj;'. N'est-ce pas la manière normale de libérer la mémoire associée à un objet? J'ai réalisé qu'il invoque automatiquement le destructeur ... est-ce normal?


Voici un extrait de code:

    if(node->isleaf())
    {
        vector<string> vec = node->L;
        vec.Push_back(node->code);
        sort(vec.begin(), vec.end());

        Mesh* msh = loadLeaves(vec, node->code);

        Simplification smp(msh);

        smp.simplifyErrorBased(errorThreshold);

        int meshFaceCount = msh->faces.size();

        saveLeaves(vec, msh);

        delete msh;
    }

loadleaves() est une fonction qui lit un maillage à partir du disque et crée un objet Mesh et le renvoie. (pensez à vec et node->code ne sont que des informations sur le fichier à ouvrir)

Dois-je supprimer la ligne delete msh;?

27
Nima

N'est-ce pas la manière normale de libérer la mémoire associée à un objet?

C'est une façon courante de gérer la mémoire allouée dynamiquement, mais ce n'est pas une bonne façon de le faire. Ce type de code est fragile car il n'est pas à l'abri des exceptions: si une exception est levée entre le moment où vous créez l'objet et le moment où vous le supprimez, vous perdrez cet objet.

Il est préférable d'utiliser un conteneur de pointeur intelligent, que vous pouvez utiliser pour obtenir une gestion des ressources liée à la portée (il est plus communément appelé l'acquisition des ressources est l'initialisation , ou RAII).

Comme exemple de gestion automatique des ressources:

void test()
{
    std::auto_ptr<Object1> obj1(new Object1);

} // The object is automatically deleted when the scope ends.

Selon votre cas d'utilisation, auto_ptr peut ne pas fournir la sémantique dont vous avez besoin. Dans ce cas, vous pouvez envisager d'utiliser shared_ptr.

Quant à savoir pourquoi votre programme se bloque lorsque vous supprimez l'objet, vous n'avez pas donné suffisamment de code pour que quiconque puisse répondre à cette question avec certitude.

37
James McNellis

Votre code utilise en effet la manière normale de créer et de supprimer un objet dynamique. Oui, il est parfaitement normal (et en effet garanti par le standard du langage!) Que delete appelle le destructeur de l'objet, tout comme new doit appeler le constructeur.

Si vous n'étiez pas en train d'instancier Object1 directement mais une sous-classe de celle-ci, je vous rappelle que toute classe destinée à être héritée doit avoir un destructeur virtuel (afin que le destructeur de la sous-classe correcte puisse être invoqué dans des cas analogues à celui-ci) - mais si votre exemple de code est en effet représentatif de votre code réel, cela ne peut pas être votre problème actuel - doit être autre chose, peut-être dans le code destructeur que vous ne nous montrez pas, ou une corruption de tas dans le code que vous '' ne s'affiche pas dans cette fonction ou dans celles qu'elle appelle ...?

BTW, si vous allez toujours supprimer l'objet juste avant de quitter la fonction qui l'instancie, il est inutile de rendre cet objet dynamique - déclarez-le simplement comme local (classe de stockage auto, comme c'est la variable par défaut) de ladite fonction!

7
Alex Martelli

N'est-ce pas la manière normale de libérer la mémoire associée à un objet?

Oui, ça l'est.

J'ai réalisé qu'il invoque automatiquement le destructeur ... est-ce normal?

Oui

Assurez-vous que vous n'avez pas double suppression votre objet.

3
Prasoon Saurav

s'il se bloque sur la ligne delete, alors vous avez presque certainement corrompu le tas. Nous aurions besoin de voir plus de code pour diagnostiquer le problème car l'exemple que vous avez présenté ne contient aucune erreur.

Vous avez peut-être un débordement de tampon sur le tas qui a corrompu les structures de tas ou même quelque chose d'aussi simple qu'un "double free" (ou dans le cas c ++ "double delete").

En outre, comme l'a noté The Fuzz, vous pouvez également avoir une erreur dans votre destructeur.

Et oui, il est tout à fait normal et attendu que delete invoque le destructeur, c'est en fait l'un de ses deux objectifs (appeler destructeur puis libérer de la mémoire).

2
Evan Teran

saveLeaves(vec,msh);
Je suppose qu'il prend le pointeur msh et le place à l'intérieur de vec. Puisque msh n'est qu'un pointeur vers la mémoire, si vous le supprimez, il sera également supprimé à l'intérieur du vecteur.

2
Brandon York