OVH Cloud OVH Cloud

Norme C++ destructeur et operateur delete []

1 réponse
Avatar
Mathieu Peyréga
Bonjour,

je me pose pas mal de questions au sujet des destructeurs virtuels, de
l'opérateur delete []...
J'ai cru voir dans la norme que le comportement lorsqu'on l'utilise avec
du polymorphisme, le comportement n'est alors pas défini (contrairement
à l'operateur delete ) et cela me parait assez génant...

Par exemple, le code suivant donne des resultats différents entre intel
8.0 vc 6.0 sp6 et MingW gcc 3.3.3.

Les 3 derniers donnent un résultat à l'exécution qui me parait cohérent
(~B est bien apellé), le premier non (~B n'est JAMAIS apellé) et je
n'ose supposer que ce soit un bug du compilateur parce qu'alors ce
serait carrément énorme... Aurais-je donc bien interpreté la norme ? Je
trouve ça bizarre, pourquoi est-ce que le comportement serait défini
pour delete et pas pour delete [] ?

Merci, pour vos réponses

Mathieu

Le code est le suivant :

--

#include <iostream>

struct A
{
inline A(void) { std::cout << "Appel de A::A()" <<
std::endl; }
inline A(A const& obj) { std::cout << "Appel de A::A(A
const& obj)" << std::endl; }
inline A& operator=(A const& obj) { std::cout << "Appel de A&
A::operator=(A const& obj)" << std::endl; return *this; }
inline virtual ~A(void) { std::cout << "Appel de A::~A()" <<
std::endl; }

}; // struct A

struct B : public A
{
inline B(void) { std::cout << "Appel de B::B()" <<
std::endl; }
inline B(B const& obj) { std::cout << "Appel de B::B(B
const& obj)" << std::endl; }
inline B& operator=(B const& obj) { std::cout << "Appel de B&
B::operator=(B const& obj)" << std::endl; return *this; }
inline virtual ~B(void) { std::cout << "Appel de B::~B()" <<
std::endl; }

}; // struct B

int main(int argc, char* argv[])
{
{
A* tabA = ::new B[2];
::delete [] tabA;

B* tabB = ::new B[2];
::delete [] tabB;

}

system("PAUSE");
return 0;
}

1 réponse

Avatar
Ivan Vecerina
"Mathieu Peyréga" wrote in message
news:
je me pose pas mal de questions au sujet des destructeurs virtuels, de
l'opérateur delete []...
...

Par exemple, le code suivant donne des resultats différents entre intel
8.0 vc 6.0 sp6 et MingW gcc 3.3.3.
...

struct B : public A
...


B* tabB = ::new B[2];
::delete [] tabB;


Code valide: doit appeler le destructeur B::~B() pour
les deux instances allouées.


A* tabA = ::new B[2];
::delete [] tabA;
Comportement indéfini (Undefined Behavior).


Tableaux d'objets et sous-classes ne font pas bon ménage.
Après la conversion implicite dans:
A* tabA = ::new B[2];
tout accès à tabA[1] conduirait à un comportement indéfini,
car B et A peuvent ne pas avoir la même taille en mémoire.
Donc delete[] ne peut pas fonctionner, et tout résultat
est possible.

La solution? : il faut éviter les tableaux d'éléments
polymorphiques, et utiliser des tableaux de pointeurs
à leur place.
(soit dit en passant, std::vector est également à préférer
à des tableaux alloués dynamiquement).

Salutations,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com