Question

Je discutais avec quelques collègues au sujet de ce qui se passe lorsque vous lancez une exception dans une classe allouée dynamiquement. Je sais que malloc est appelé, puis le constructeur de la classe. Le constructeur ne retourne jamais, donc ce qui se passe au malloc?

Prenons l'exemple suivant:

class B
{
public:
    B()
    {
        cout << "B::B()" << endl;
        throw "B::exception";
    }

    ~B()
    {
        cout << "B::~B()" << endl;          
    }
};

void main()
{
    B *o = 0;
    try
    {
        o = new B;
    }
    catch(const char *)
    {
        cout << "ouch!" << endl;
    }
}

Qu'est-ce qui arrive à la o mémoire malloced, est-il une fuite? Le CRT Intercepter l'exception du constructeur et liberer la mémoire?

Vive!
Rich

Était-ce utile?

La solution

Un appel à

new B();

se résorbe en deux choses:

  • allocation avec un opérateur nouveau () (soit une ou spécifique de classe mondiale, ce qui pourrait un placement dont une avec la syntaxe new (xxx) B())
  • appeler le constructeur.

Si le jet du constructeur, l'opérateur correspondant est appelé delete. Le cas où la suppression correspondante est un placement un est le seul cas où un opérateur supprimer le placement est appelée sans la syntaxe opérateur :: delete (). delete x; ou delete[] x; ne remet pas le placement supprimer les opérateurs et il n'y a pas de syntaxe similaire au placement nouveau pour les appeler.

Notez que si le destructor de B pas s'appeler, déjà construits (sous-objets membres ou des classes B et la base B) sera détruite avant que l'appel à l'opérateur supprimer. Le constructeur qui n'est pas appelé est celui B.

Autres conseils

Quand une exception est levée à partir du constructeur, la mémoire allouée par la nouvelle est libérée, mais la destructor de la classe B est pas appelée.

Dans ce cas, votre objet, o, ne sont pas réellement construits, et la mémoire allouée par la nouvelle est libérée. En tant que tel, ne l'destructor pas appelée. Donc, vous ne devez pas appeler:

delete o;

Un modèle de conception intéressante est RAII - Acquisition des ressources est Initialisation. Dans ce modèle, vous utilisez un constructeur pour encapsuler l'acquisition d'une ressource, et libérer la ressource dans le destructor. Si la ressource ne peut être acquise, vous jetez dans le constructeur - un peu comme votre exemple. Ainsi, si vous avez un objet valide, vous avez la ressource.

Si l'objet est construit, vous avez acquis avec succès la ressource. Cela signifie que pour la vie de l'objet, vous possédez la ressource. Lorsque l'objet est supprimé, la ressource est libérée. Si l'objet est jamais construit, alors vous n'acquis la ressource. Voir wikipedia:

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

De C ++ 2003 Standard 5.3.4 / 17 - Nouveau:

  

Si une partie de l'initialisation de l'objet décrit ci-dessus se termine en lançant une exception et une fonction de désallocation approprié peut être trouvé, la fonction de désallocation est appelé pour libérer la mémoire dans laquelle l'objet a été construit, après quoi l'exception continue à se propager dans le cadre de la nouvelle expression. Si aucune fonction de désaffectation correspondant sans ambiguïté peut être trouvée, la propagation de l'exception ne provoque pas la mémoire de l'objet à être libéré. [Note: Ceci est approprié lorsque la fonction d'allocation appelée n'alloue pas de mémoire; sinon, il est susceptible d'entraîner une fuite de mémoire. ]

Il y a peut ou ne peut pas être une fuite - cela dépend si un deallocator approprié se trouve (ce qui est normalement le cas, à moins que l'opérateur nouvelle / suppression ont été réinitialisée) .Dans le cas où il y a un deallocator approprié, la compilateur est responsable pour le câblage dans un appel si le constructeur jette.

Notez que ceci est plus ou moins sans rapport avec ce qui se passe aux ressources acquises dans le constructeur, ce qui est ma première tentative de réponse discutée -. Et est une question qui est discutée dans de nombreux FAQ, des articles et des messages

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top