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

1 2 3 4 5
Avatar
Gabriel Dos Reis
Yoxoman writes:

|
| > Si tu es débutant, comme tu l'indiques dans le sujet, je te suggèrrerais
| > de laisser de côté la gestion manuelle d'allocation dynamique et d'y
| > revenir bien plus tard, quand tu as compris certaines notions
| > fondamentales de C++. En particuloer, je te suggèrerais d'utiliser le
| > type standard std:vector<int>.
|
| Oki. J'ai tout de même une question stupide : y a-t-il une classe
| équivalente pour les matrices ?

Non, mais il y a une classe déjà mentionnée dans ce thread : valarray<>.
Elle est cependant un peu délicate d'utilisation. Elle support les
opérations BLAS de niveau 1. Tu peux bâtir les opérations BLAS de
d'ordre supérieure dessus.

| Sinon, je me doute qu'on peut utiliser std::vector avec une taille de
| nbLignes*nbColonnes.

Oui, grosso mode, si tu utilisais valarray<>, c'est ce que tu ferais :
allouer un n * m, et utiliser les std::slice() ou std::gslice().

Mais tu pourrais commencer avec std::vector<>.

-- Gaby
Avatar
Gabriel Dos Reis
Olivier Azeau writes:

[...]

| Un développeur qui connait pas trop mal Java et qui se met au C++ ça
| ressemble un peu à un qqun qui a appris à conduire avec une boite
| automatique et se met à conduire avec une boite manuelle : il connait
| le volant, l'accélérateur et le frein mais s'il reste en 1ère, il
| n'ira pas bien loin.
|
| C'est pour cela que je trouve dangereux d'apprendre le C++ avec toute
| la STL comme "faisant partie du langage".
| La STL est au C++, ce que le régulateur de vitesse automatique est à
| la conduite : un fabuleux outil pour celui qui le maîtrise et un bon
| moyen de finir dans le décor pour les autres.


Proof by analogy is fraud. Comme nous allons le voir.
Olivier nous énonce :

Un développeur qui connait pas trop mal Java et qui se met au C++ ça
ressemble un peu à un qqun qui a appris à conduire avec une boite
automatique et se met à conduire avec une boite manuelle : il connait
le volant, l'accélérateur et le frein mais s'il reste en 1ère, il
n'ira pas bien loin.

Et il en déduit :

C'est pour cela que je trouve dangereux d'apprendre le C++ avec toute
la STL comme "faisant partie du langage".

Où est le lien ? Il continue l'analgie avec

La STL est au C++, ce que le régulateur de vitesse automatique est à
la conduite : un fabuleux outil pour celui qui le maîtrise et un bon
moyen de finir dans le décor pour les autres.

sans toujours préciser pourquoi son analogie est pertinente et quel
est le rôle de Java dans cette analogie.

-- Gaby
Avatar
Olivier Azeau
Gabriel Dos Reis wrote:

Proof by analogy is fraud. Comme nous allons le voir.


Phrase typiquement "S" en réponse à une argumentation "N" - cf
http://en.freepedia.org/Myers-Briggs_Type_Indicator.html
Il en est de même pour la décomposition par étapes qui suit.
Je vais donc essayer de détailler mes propos.

Olivier nous énonce :

Un développeur qui connait pas trop mal Java et qui se met au C++ ça
ressemble un peu à un qqun qui a appris à conduire avec une boite
automatique et se met à conduire avec une boite manuelle : il connait
le volant, l'accélérateur et le frein mais s'il reste en 1ère, il
n'ira pas bien loin.

Et il en déduit :

C'est pour cela que je trouve dangereux d'apprendre le C++ avec toute
la STL comme "faisant partie du langage".

Où est le lien ?



Le fait est que Java ressemble syntaxiquement au C++ alors que dans le
fond ça n'a strictement rien à voir (particulièrement sur les aspects
gestion mémoire) tout comme 2 voitures qui sont en apparence semblables
mais dont le système de transmission est totalement différent et qui
donc se conduisent différemment.

Programmer en C++ sans se soucier du comment les choses sont organisées
en mémoire, c'est utiliser le C++ comme du Java.
Programmer avec la STL sans maîtriser les templates, c'est la même chose
: on ne maîtrise pas le comportement mémoire de ce que l'on utilise.
Il y a certaines choses essentielles à apprendre *en premier* et se
palucher des problèmes de gestion mémoire en fait partie.

Le langage C++ d'aujourd'hui n'est pas "vachement différent" comme tu le
dis si bien. C'est toujours le même. Certes, la façon de l'utiliser
change car il y a une communauté très vivante mais les problèmes
fondamentaux restent.
De plus, tout le monde ne s'appelle pas Alexander Stepanov ou Andrei
Alexandrescu...

Il continue l'analgie avec

La STL est au C++, ce que le régulateur de vitesse automatique est à
la conduite : un fabuleux outil pour celui qui le maîtrise et un bon
moyen de finir dans le décor pour les autres.

sans toujours préciser pourquoi son analogie est pertinente et quel
est le rôle de Java dans cette analogie.



Une analogie est là pour susciter de nouvelles connexions mentales sur
un sujet donné en y apportant un angle de vision différent.
Si on l'explique mot à mot, elle ne sert pour ainsi dire à rien car
l'explication enlève au lecteur l'effort d'appréhension de cette vision
différente.
Tout comme conseiller à un débutant C++ de ne pas se préoccupper de
problèmes de gestion mémoire lui occulte un pan essentiel de "comment
fonctionne ce langage" :-)

Olivier.

Avatar
Olivier Azeau
Yoxoman wrote:


(...) Pour rappel, appeler delete sur un pointeur null est une opération tout
à fait valide qui en fait ne fait rien (pas besoin de tester la nullité
du pointeur).



Merci beaucoup pour toutes ces informations.


Pas de quoi.

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;


Avatar
Gabriel Dos Reis
Olivier Azeau writes:

| Gabriel Dos Reis wrote:
| > Proof by analogy is fraud. Comme nous allons le voir.
|
| Phrase typiquement "S" en réponse à une argumentation "N" - cf
| http://en.freepedia.org/Myers-Briggs_Type_Indicator.html
| Il en est de même pour la décomposition par étapes qui suit.
| Je vais donc essayer de détailler mes propos.
|
| > Olivier nous énonce :
| > Un développeur qui connait pas trop mal Java et qui se met au
| > C++ ça
| > ressemble un peu à un qqun qui a appris à conduire avec une boite
| > automatique et se met à conduire avec une boite manuelle : il connait
| > le volant, l'accélérateur et le frein mais s'il reste en 1ère, il
| > n'ira pas bien loin.
| > Et il en déduit :
| > C'est pour cela que je trouve dangereux d'apprendre le C++ avec
| > toute
| > la STL comme "faisant partie du langage".
| > Où est le lien ?
| >
|
| Le fait est que Java ressemble syntaxiquement au C++ alors que dans le
| fond ça n'a strictement rien à voir (particulièrement sur les aspects
| gestion mémoire) tout comme 2 voitures qui sont en apparence
| semblables mais dont le système de transmission est totalement
| différent et qui donc se conduisent différemment.

Mais C++ et Java ne sont pas des voitures. Tu ne montres pas le
rapport entre l'apprentissage de la programmtaion, de la programmation
en C++ ou de la programmation en Java et l'apprentissage de la
conduite. Et pourquoi ce rapport est pertinent pour comprendre ce dont
tu parles. Tu te contentes juste d'assener l'assertion comme si elle
était une vérité révelée ; et c'est justement là l'interrogation.

| Programmer en C++ sans se soucier du comment les choses sont
| organisées en mémoire, c'est utiliser le C++ comme du Java.

Pourquoi ?

| Programmer avec la STL sans maîtriser les templates, c'est la même
| chose : on ne maîtrise pas le comportement mémoire de ce que l'on
| utilise.

Pour quelles raisons ?

[ De fait, des expériences concrêtes conduites en grandeur nature ici
avec des « freshmen » suggèrent une meilleur compréhension de ces
notions avancées. En fait, on leur a enseigné la gestion manuelle de la
mémoire bien après l'héritage, les fonctions virtuelles et les
templates. Je parle par exemple de cette année d'une classe de plus de
deux élèves et une évaluation de chacun de ces élèvent. ]

[...]

| Une analogie est là pour susciter de nouvelles connexions mentales sur
| un sujet donné en y apportant un angle de vision différent.

Sauf qu'ici tu ne fais pas de connexions mentales (je dirais plutôt
frauduleuses) car tu déduis de cette analogie

Il est donc aisé d'induire le comportement de l'un par ce que l'on
connait de l'autre.

sans avoir montré pourquoi cette analogie était pertinente.
C'est de la fraude.

-- Gaby
Avatar
Gabriel Dos Reis
Gabriel Dos Reis writes:

| [ De fait, des expériences concrêtes conduites en grandeur nature ici
| avec des « freshmen » suggèrent une meilleur compréhension de ces
| notions avancées. En fait, on leur a enseigné la gestion manuelle de la
| mémoire bien après l'héritage, les fonctions virtuelles et les
| templates. Je parle par exemple de cette année d'une classe de plus de
| deux élèves et une évaluation de chacun de ces élèvent. ]
^

« cents »

aaargh.

-- Gaby
Avatar
usenet04
Olivier Azeau :

| Une analogie est là pour susciter de nouvelles connexions mentales sur
| un sujet donné en y apportant un angle de vision différent.
| Si on l'explique mot à mot, elle ne sert pour ainsi dire à rien car
| l'explication enlève au lecteur l'effort d'appréhension de cette
| vision différente.

Encore faudrait-il que l'analogie soit pertinente. Ici, on pourrait
échanger "STL" et "allocation dynamique" pour faire une affirmation
tout aussi gratuite et complètement opposée sur le fond. Il faudrait
donc justifier en quoi cette analogie-là est correcte et pas
l'autre. Et comme l'a dit Gaby, c'est au mieux de l'illustration, pas
de l'argumentation.

Et en général, l'analogie sert à éclaircir quelque chose en comparant
à un sujet connu. Ici, le sujet connu c'est le C++, changer le
contexte ne simplifie pas les choses, bien au contraire, on y perd
beaucoup. Ce serait différent s'il s'agissait d'expliquer quelque
chose à un débutant (qui ne connaît donc pas le C++) et pour qui
l'analogie serait plus claire, mais on n'est pas dans ce cadre-là.
Avatar
Olivier Azeau
Gabriel Dos Reis wrote:
Olivier Azeau writes:
| Programmer en C++ sans se soucier du comment les choses sont
| organisées en mémoire, c'est utiliser le C++ comme du Java.

Pourquoi ?


Parce qu'on ne s'inquiète alors pas de tout ce qui peut corrompre un
pointeur et des conséquences que cela entraine.


| Programmer avec la STL sans maîtriser les templates, c'est la même
| chose : on ne maîtrise pas le comportement mémoire de ce que l'on
| utilise.

Pour quelles raisons ?


Parce ce qu'on ne sait pas ce qui se passe sans une lecture
hyper-attentive des docs et même quelquefois un petit saut dans le code
source.
cf par exemple l'opérateur [] de std::vector qui est loin d'être un
modèle d'interface intuitive.
Comment expliquer qu'il faut d'abord passer par un resize ou un
push_back et qu'il vaut mieux utiliser at plutôt que [], tout ça sans
aborder un minimum de gestion mémoire ?

Par un malheureux hasard, le java.util.vector n'a pas ce genre de problèmes.


[ De fait, des expériences concrêtes conduites en grandeur nature ici
avec des « freshmen » suggèrent une meilleur compréhension de ces
notions avancées. En fait, on leur a enseigné la gestion manuelle de la
mémoire bien après l'héritage, les fonctions virtuelles et les
templates. Je parle par exemple de cette année d'une classe de plus de
deux élèves et une évaluation de chacun de ces élèvent. ]



J'ai du mal à cerner comment on peut évaluer la compréhension de la
gestion mémoire dans un contexte de cursus universitaire.
Le fait est que je n'ai pour ainsi dire jamais connu un développeur C++
qui n'a pas eu un jour ou l'autre un problème de gestion mémoire. Cela
n'est pas vrai pour les autres notions.
Par problème, j'entends ici mise en péril de l'exécution d'une application.


Olivier.

Avatar
usenet04
Olivier Azeau :

| Le fait est que je n'ai pour ainsi dire jamais connu un développeur
| C++ qui n'a pas eu un jour ou l'autre un problème de gestion
| mémoire. Cela n'est pas vrai pour les autres notions.

C'est bien pour ça qu'il vaut mieux commencer par ce qui est plus
simple, et n'aborder ce sujet qu'après avoir vu les bases du C++.
Avatar
Gabriel Dos Reis
Olivier Azeau writes:

| Gabriel Dos Reis wrote:
| > Olivier Azeau writes:
| > | Programmer en C++ sans se soucier du comment les choses sont
| > | organisées en mémoire, c'est utiliser le C++ comme du Java.
| > Pourquoi ?
|
| Parce qu'on ne s'inquiète alors pas de tout ce qui peut corrompre un
| pointeur et des conséquences que cela entraine.

Cela n'est pas du tout vrai. Je peux utiliser correctement (ainsi que
mes élèves) std::vector<> ou std::list<> sans me soucier de comment
les allocateurs marchent.

| > | Programmer avec la STL sans maîtriser les templates, c'est la même
| > | chose : on ne maîtrise pas le comportement mémoire de ce que l'on
| > | utilise.
| > Pour quelles raisons ?
|
| Parce ce qu'on ne sait pas ce qui se passe sans une lecture
| hyper-attentive des docs et même quelquefois un petit saut dans le
| code source.

C'est un axiome ? Parce que des expériences grandeur nature montrent
quotidiennement le contraire.

| cf par exemple l'opérateur [] de std::vector qui est loin d'être un
| modèle d'interface intuitive.

Dans notre cours, std::vector<T>::operator[] est vérifié par défaut,
et on ne leur montre la verié hardcore que bien plus tard.

| Comment expliquer qu'il faut d'abord passer par un resize ou un
| push_back et qu'il vaut mieux utiliser at plutôt que [], tout ça sans
| aborder un minimum de gestion mémoire ?

Un tableau est une suite dynamique, i.e. dont le nombre d'éléments
varie au cours du programme et [] ne travaille que sur les eléments
dans le tableau. Tu peux en ajouter en faisant un push_back() -- qui
mettra l'élément à la fin.
Pourquoi vouloir insister sur la gestion manuelle ici pour expliquer
comment vector<> marche avec des opérations aussi simples ?

| Par un malheureux hasard, le java.util.vector n'a pas ce genre de problèmes.

C'est bien (ou mal) pour Java.

|
| > [ De fait, des expériences concrêtes conduites en grandeur nature ici
| > avec des « freshmen » suggèrent une meilleur compréhension de ces
| > notions avancées. En fait, on leur a enseigné la gestion manuelle de la
| > mémoire bien après l'héritage, les fonctions virtuelles et les
| > templates. Je parle par exemple de cette année d'une classe de plus de
| > deux élèves et une évaluation de chacun de ces élèvent. ]
| >
|
| J'ai du mal à cerner comment on peut évaluer la compréhension de la
| gestion mémoire dans un contexte de cursus universitaire.

Cela explique beaucoup de tes messages. Cela n'est pas parce que tu as
du mal à l'imaginer que cela ne se passe pas dans le concret.

| Le fait est que je n'ai pour ainsi dire jamais connu un développeur
| C++ qui n'a pas eu un jour ou l'autre un problème de gestion
| mémoire.

Oui, mais la notion de gestion de mémoire ou de resource en général
est un problème que j'estime on ne peut sérieusement attaquer ou
comprendre si on n'a pas les B A BA solides dans la tête. Il n'a
jamais été question de la n7égliger, juste de l'aborder quand on a une
certaine compréhension des fondamentaux.

| Cela n'est pas vrai pour les autres notions.
| Par problème, j'entends ici mise en péril de l'exécution d'une application.
|
|
| Olivier.

--
Gabriel Dos Reis

1 2 3 4 5