OVH Cloud OVH Cloud

[Debutant] Probleme de destruction

120 réponses
Avatar
Yoxoman
Bonjour à tous.

Je me permet de vous soumettre ce petit programme, qui représente en
gros la partie qui me pose problème d'un truc plus gros :

#include <iostream>

using namespace std;

class Vecteur
{
public:
double *val;
int taille;

Vecteur() {}
Vecteur(int i);
~Vecteur() {cout << "detruit" << endl; delete[] val;}

Vecteur foisDeux();
Vecteur &operator=(const Vecteur &v);
};

Vecteur::Vecteur(int i)
{
taille=i;
val=new double[i];
}

Vecteur Vecteur::foisDeux()
{
Vecteur temp(taille);

for (int i=0; i<taille; i++)
{
temp.val[i]=2*val[i];
}

return temp; //(1)
}

Vecteur &Vecteur::operator=(const Vecteur &v)
{
taille=v.taille;
val=new double[taille];

for (int i=0; i<taille; i++)
{
val[i]=v.val[i];
}

return *this;
}

int main(void)
{
Vecteur v1(3);
Vecteur v2;

v2=v1.foisDeux(); //(2)

return 0;
}

Segmentation fault.
J'ai tout d'abord eu du mal à identifier le problème, mais j'ai réussi
grâce à des supers pouvoirs hérités de Goldorak.
En fait, à la fin de la fonction foisDeux(), la variable temporaire
temp est détruite. Logique. En même temps, la fonction renvoie une
copie de l'objet, qui possède donc dans ses attributs un pointeur sur
une zone mémoire inaccessible (action du delete[]). Problème donc à la
destruction de ce dernier.

En fait, je ne sais pas trop comment arranger ce problème. Je ne
voudrais pas modifier *directement* les attributs de v1 dans la
fonction foisDeux(), pour garder ce vecteur en stock.

Merci d'avance pour votre aide.

10 réponses

Avatar
Olivier Azeau
Loïc Joly wrote:

Ce genre de question piège pour mauvais élève ne me gêne pas. Ce qui me


Ben moi ce qui me gêne c'est que sur 2 entretiens, je vois au minimum 1
"mauvais élève".

gêne plus, c'est de voir du code du style :

class math
{
public:
static double sin(double x);
};


Qu'est-ce qui est gênant dans ce code ?


Ou encore plus courant :

class A
{ // ...
};

int main()
{
A *a = new A;
delete a;
}

Au lieu de :
int main()
{
A a;
}



Oui...
Mais tu fais quoi quand tu as une librairie tierce qui ne te propose que
des factories qui créent dans le tas et que tu n'as besoin de l'objet
que le temps d'un appel de fonction ?

Avatar
Olivier Azeau
Gabriel Dos Reis wrote:

Je plains tes élèves ou ceux à qui tu dois enseigner C++.

Ca tombe bien : je n'enseigne à personne !

(Je ne fais que constater les lacunes de ceux à qui on l'a enseigné...)

Avatar
usenet04
Olivier Azeau :

| Un peu quand même non si on reprend le sujet initial du thread ?
| Et même si certains interlocuteurs connaissent très bien le C++,
| j'estime que cela peut au moins montrer comment "l'autre" perçoit les
| choses.

Oui, ça peut être utile pour ça en effet. Mais dans le cas présent, je
pense que ton propos était assez clair dès le départ, même sans
analogie.
Avatar
Gabriel Dos Reis
Olivier Azeau writes:

| Gabriel Dos Reis wrote:
| > Je plains tes élèves ou ceux à qui tu dois enseigner C++.
| >
| Ca tombe bien : je n'enseigne à personne !
| (Je ne fais que constater les lacunes de ceux à qui on l'a enseigné...)

Aha, ceci explique cela.

-- Gaby
Avatar
Gabriel Dos Reis
Olivier Azeau writes:

| Mais tu fais quoi quand tu as une librairie tierce qui ne te propose
| que des factories qui créent dans le tas et que tu n'as besoin de
| l'objet que le temps d'un appel de fonction ?

Mauvais fournisseur, changer de fournisseur. Ou, si la chose est
important pour le projet, investir dedans. Si ce n'est pas important
pour le projet, ...

-- Gaby
Avatar
Luc Hermitte
Olivier Azeau wrote in
news:XUIud.3517$:

Quand tu auras dépatouillé tout ça, le prochain problème qui devrait
survenir, ça sera probablement qqe chose comme :

Vecteur v(5);
v = v;


Tant qu'il travaille dans l'ordre (préparation d'un buffer temporaire avant
destruction/échange) il n'y a aucun problème.


--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

Avatar
Luc Hermitte
Yoxoman wrote in news:MPG.1c24cea320cd52a19896b0
@news.free.fr:

Oki. J'ai tout de même une question stupide : y a-t-il une classe
équivalente pour les matrices ?
Sinon, je me doute qu'on peut utiliser std::vector avec une taille de
nbLignes*nbColonnes.


Il n'y a rien d'immédiat en standard. En revanche, il existe toutes fois
diverses bibliothèques matricielles tierces, qui sont optimisées et prêtes
à l'emploi.


--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

Avatar
Olivier Azeau
Luc Hermitte wrote:
Olivier Azeau wrote in
news:XUIud.3517$:


Quand tu auras dépatouillé tout ça, le prochain problème qui devrait
survenir, ça sera probablement qqe chose comme :

Vecteur v(5);
v = v;



Tant qu'il travaille dans l'ordre (préparation d'un buffer temporaire avant
destruction/échange) il n'y a aucun problème.


Oui. Je voulais juste signaler à Yoxoman qui n'a peut être pas

l'habitude de ce genre de problèmes que c'est un test unitaire
"standard" à prévoir pour ce genre de classes.
Enfin bon... C'est juste ma façon de voir les choses : prévoir une
batterie de tests unitaires pour les cas un peu limites. Ca aide surtout
à éviter de se poser trop de questions quand on revient plus tard sur le
code d'une classe pour y modifier des trucs.

Sur la façon d'éviter le problème, je préfère pour ma part rajouter
"if(&v == this) return *this;" qui est beaucoup plus explicite.


Avatar
Olivier Azeau
Gabriel Dos Reis wrote:
Olivier Azeau writes:

| Mais tu fais quoi quand tu as une librairie tierce qui ne te propose
| que des factories qui créent dans le tas et que tu n'as besoin de
| l'objet que le temps d'un appel de fonction ?

Mauvais fournisseur, changer de fournisseur. Ou, si la chose est
important pour le projet, investir dedans. Si ce n'est pas important
pour le projet, ...

Oui, c'est beau la théorie...

En fait un cas encore plus courant est l'objet allouable sur la pile qui
crée systématiquement une implémentation dans le tas (cas typique
d'isolation pour minimiser les dépendances binaires)

La bonne réponse (de mon point de vue) est :
1) l'allocation/desallocation au sein d'un même bloc est acceptable
quand d'autres contraintes la justifient.
2) si elle finit par *éventuellement* poser problème (de perf
notamment), alors on envisage une solution (typiquement la réutilisation
via un pool d'instances)

Avatar
Olivier Azeau
Gabriel Dos Reis wrote:
Olivier Azeau writes:

| Gabriel Dos Reis wrote:
| > Je plains tes élèves ou ceux à qui tu dois enseigner C++.
| >
| Ca tombe bien : je n'enseigne à personne !
| (Je ne fais que constater les lacunes de ceux à qui on l'a enseigné...)

Aha, ceci explique cela.

Si tu le dis...