OVH Cloud OVH Cloud

boost::scoped_ptr et exception

6 réponses
Avatar
Michael
Bonjour à tous,

j'ai un petit souci de libération de la mémoire avec l'exemple suivant.

Soit la classe exemple suivante:

class toto
{
private:
boost::scoped_ptr<foo1> f1;
boost::scoped_ptr<foo2> f2;
boost::scoped_ptr<foo3> f3;
public:
toto() {}
void Set(int i);
};

void toto::Set(int i)
{
f1.reset(new foo1(i));
f2.reset(new foo2(i));
f3.reset(new foo3(i)); //Exception lancée
}

Si par exemple une exception est lancée sur la troisième ligne, et que je
quitte l'application, j'ai un message de CodeGuard (une sorte Valgrind je
crois) me disant que la mémoire allouée pour f1 et f2 n'a pas été libérée...

Je trouve ça bizarre, je pensais que le pointeur intelligent était justement
fait pour ça...

Ou alors je me trompe?

Merci pour vos lanternes

Mike

6 réponses

Avatar
Mathias Gaunard

void toto::Set(int i)
{
f1.reset(new foo1(i));
f2.reset(new foo2(i));
f3.reset(new foo3(i)); //Exception lancée
}

Si par exemple une exception est lancée sur la troisième ligne, et que je
quitte l'application, j'ai un message de CodeGuard (une sorte Valgrind je
crois) me disant que la mémoire allouée pour f1 et f2 n'a pas été libérée...


Tu as un try/catch global ?

Avatar
Michael
Tu as un try/catch global ?


Oui, j'ai le code suivant avec BCB6

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}

Avatar
James Kanze
Michael wrote:

j'ai un petit souci de libération de la mémoire avec l'exemple suivan t.

Soit la classe exemple suivante:

class toto
{
private:
boost::scoped_ptr<foo1> f1;
boost::scoped_ptr<foo2> f2;
boost::scoped_ptr<foo3> f3;
public:
toto() {}
void Set(int i);
};

void toto::Set(int i)
{
f1.reset(new foo1(i));
f2.reset(new foo2(i));
f3.reset(new foo3(i)); //Exception lancée
}

Si par exemple une exception est lancée sur la troisième ligne, et qu e je
quitte l'application, j'ai un message de CodeGuard (une sorte Valgrind je
crois) me disant que la mémoire allouée pour f1 et f2 n'a pas été libérée...


Est-ce que le destructeur de l'instance to toto a été appelé ?
C'est là qu'on va libérer la mémoire.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Michael
Est-ce que le destructeur de l'instance to toto a été appelé ?
C'est là qu'on va libérer la mémoire.


toto est un membre d'une autre classe...

class toto
{
private:
boost::scoped_ptr<foo1> f1;
boost::scoped_ptr<foo2> f2;
boost::scoped_ptr<foo3> f3;
public:
toto() {}
void Set(int i);
};

void toto::Set(int i)
{
f1.reset(new foo1(i));
f2.reset(new foo2(i));
f3.reset(new foo3(i)); //Exception lancée
}

class Video
{
private:
toto t;
public:
Video();
void t();
};

void Video::t()
{
t.Set(3);
}

Donc à la fin du programme, le destructeur de toto est bien appellé, non?

Avatar
Mathias Gaunard

j'ai un petit souci de libération de la mémoire avec l'exemple suivant.

Soit la classe exemple suivante:

class toto
{
private:
boost::scoped_ptr<foo1> f1;
boost::scoped_ptr<foo2> f2;
boost::scoped_ptr<foo3> f3;
public:
toto() {}
void Set(int i);
};

void toto::Set(int i)
{
f1.reset(new foo1(i));
f2.reset(new foo2(i));
f3.reset(new foo3(i)); //Exception lancée
}


Essaie de faire un exemple minimal réduit que l'on peut compiler et qui
montre le problème.

Avatar
James Kanze
On Feb 20, 11:23 am, Michael <michael.at.gmail.dot.com> wrote:
Est-ce que le destructeur de l'instance to toto a été appelé ?
C'est là qu'on va libérer la mémoire.


toto est un membre d'une autre classe...

class toto
{
private:
boost::scoped_ptr<foo1> f1;
boost::scoped_ptr<foo2> f2;
boost::scoped_ptr<foo3> f3;
public:
toto() {}
void Set(int i);
};

void toto::Set(int i)
{
f1.reset(new foo1(i));
f2.reset(new foo2(i));
f3.reset(new foo3(i)); //Exception lancée
}

class Video
{
private:
toto t;
public:
Video();
void t();

};

void Video::t()
{
t.Set(3);

}

Donc à la fin du programme, le destructeur de toto est bien appellé, non?


Quand tu appelles le destructeur de l'autre classe, le
destructeur de toto est appelé.

Toute la question, c'est où et comment l'objet complet a été
alloué. Si c'est un objet static, le destructeur serait appelé à
la fin du programme. Si c'est un objet alloué dynamiquement
(opérateur new), le destructeur serait appelé quand tu invoques
delete (et jamais, si tu n'invoques jamais delete sur l'objet),
si c'est un objet local non static, le destructeur serait appelé
quand tu quittes la portée de l'objet -- et seulement si tu en
quittes la portée ; un appel à exit() ou abort(), par exemple,
termine le programme sans quitter la portée de la fonction
appelant. (En règle général, on n'appelle pas exit() en C++ ;
on retourne de main.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34