Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3945 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

pb àl'execution car prog trop gros pour DEV-CPP

n°969611
bjone
Insert booze to continue
Posté le 02-02-2005 à 16:43:04  profilanswer
 

Reprise du message précédent :
oki, c'est pas ça mais:
1) si tu as des pointeurs dans ta classe
2) et que dans le destructeur tu détruits des objets pointés par les pointeurs membres
3) et que tu n'as pas implémenté l' operator = et le constructeur de recopie
 
=> tu crasheras probablement lors d'un push_back() ou autre opération sur un container de la STL.


Message édité par bjone le 02-02-2005 à 16:44:39
mood
Publicité
Posté le 02-02-2005 à 16:43:04  profilanswer
 

n°969613
bjone
Insert booze to continue
Posté le 02-02-2005 à 16:44:16  profilanswer
 

le problème du C++, c'est que pour que -ça marche- il faut que tout soit implémenté d'un coup, sinon tôt ou tard, ça parts en vrille (enfin pas forcément mais avec la STL si).


Message édité par bjone le 02-02-2005 à 16:44:55
n°969789
bjone
Insert booze to continue
Posté le 02-02-2005 à 18:10:02  profilanswer
 

bon alors pour te faire un topo:
 
soit:
 

Code :
  1. #include <string>
  2. using namespace std:
  3. class float_nomme
  4. {
  5. public:
  6.    string nom;
  7.    float valeur;
  8.    ....
  9.    ....
  10. };
  11. class etat
  12. {
  13. public:
  14.    float_nomme *pression;
  15.    ....
  16.    ....
  17.    etat()
  18.    {
  19.        pression=new float_nomme;
  20.    }
  21.    ~etat()
  22.    {
  23.        if( pression )
  24.            delete pression;
  25.    }
  26. };


 
si tu as uniquement -ça-, au push_back() d'une instance de "etat" ou autre opération, ça crashera.
 
porqué ? les diverses opérations vont à un moment vouloir copier ou assigner un "etat" à un autre ou sur un autre.
 
imaginons:
 
etat A, B;
 
A et B ont bien un "float_nomme" nommé de crée et maintenu par le pointeur "pression".
 

Code :
  1. int main()
  2. {
  3.   etat A,B;
  4.   A.pression->value=10; // OK
  5.   B.pression->nom="diamètre"; // OK
  6. }


 
jusque là ça va, mais à l'assignement si il n'y a pas d'opérateur d'assignement tout est -copié- (assigné) par défaut.
 
donc mettons que A a "pression" qui pointe sur 0x08045646 et B a son "pression" qui pointe sur 0x0564564.
 
après un:
A=B;
 
A et B auront "pression" qui pointent tous deux sur le "float_nomme" à 0x0564564.
conséquence =>
1) une modification a travers A ou à travers B atteint le même "float_nomme".
2) l'ancien "float_nomme" de A est perdu dans la nature.
3) à la destruction de A et B, le même "float_nomme" à 0x0564564 sera détruit deux fois.
=> KABOOOM
 
pour cela il faut implémenter:
1) le constructeur de recopie
2) l'opérateur d'assignement
 
1) le premier sert à créer un objet pas encore initialisé à partir d'un autre
2) le deuxième sert à écraser un objét déjà initialisé à partir d'un autre
 
donc le modèle général est:
 

Code :
  1. class etat
  2. {
  3. public:
  4.    float_nomme *pression;
  5.    ....
  6.    ....
  7.    etat()
  8.    {
  9.        pression=new float_nomme;
  10.    }
  11.    // constructeur de recopie
  12.    etat( const etat &source )
  13.    {
  14.        // à ce moment précis, pression est dans le vent (potentiellement
  15.        // alétoire)
  16.        pression= new float_nomme( *source.pression );
  17.        // maintenant pression est -valide-
  18.    }
  19.    etat &opertor = (const etat &source )
  20.    {
  21.        // protection anti-: "A=A";
  22.        if( &source != this )
  23.        {
  24.             // suppression de l'ancien
  25.             if( pression )
  26.                delete pression;
  27.            
  28.             // copie du float_nomme
  29.             pression=new float_nomme( *source.pression );
  30.        }
  31.      
  32.        return *this;
  33.    }
  34.    ~etat()
  35.    {
  36.        if( pression )
  37.            delete pression;
  38.    }
  39. };


 
voilà si je délires pas trop.
 
les "if( pression )" sont pas critiques ici, mais ça peut être une bonnée idée de le pratiquée si tu peux partir avec le pointeur "pression" à NULL (pas de float_nomme lié).
 
dans l'assignement, "pression=new float_nomme( *source.pression )" est un choix, on peut aussi penser à faire un (plus judicieux après réflexion, on assigne aussi les sous objets):
*pression = *session.pression;  
pour écraser le "float_nomme" courant par celui de la source, au lieu de supprimer le courant et de recopier celui de la source.
(le comportement est pas forcément le même, attention)
 
en espérant ne pas avoir dit de conneries (question de principe)


Message édité par bjone le 02-02-2005 à 18:14:28
n°969805
xterminhat​e
Si vis pacem, para bellum.
Posté le 02-02-2005 à 18:35:05  profilanswer
 

Ca serait p-e plus judicieux d'exploiter un pointeur intelligent pour regler son problème...


---------------
Cordialement, Xterm-in'Hate...
n°969887
Mackila
Posté le 02-02-2005 à 20:37:29  profilanswer
 

if ( truc ) delete truc ;

ca sert à rien, autant écrire directement

delete truc ;

.

n°969894
Mr Mala
Posté le 02-02-2005 à 20:45:11  profilanswer
 

Mackila a écrit :

if ( truc ) delete truc ;

ca sert à rien, autant écrire directement

delete truc ;

.


 

bjone a écrit :


les "if( pression )" sont pas critiques ici, mais ça peut être une bonnée idée de le pratiquer si tu peux partir avec le pointeur "pression" à NULL (pas de float_nomme lié).


 
Donc bjone se plante ou tu n'as pas lu son post entièrement ? :??:  
 

n°969905
Tarabiscot​e
Posté le 02-02-2005 à 21:12:16  profilanswer
 

Moi je suis d'accord avec Mackila ca sert à rien car lorsque l'on fait delete c'est déjà prévu de ne rien faire lorsque le pointeur est NULL.

n°969973
bjone
Insert booze to continue
Posté le 02-02-2005 à 22:19:17  profilanswer
 

je sais plus, sûr ?

n°969982
bjone
Insert booze to continue
Posté le 02-02-2005 à 22:29:32  profilanswer
 

oui merde, j'avais oublié. autant pour moi.

n°969998
HelloWorld
Salut tout le monde!
Posté le 02-02-2005 à 22:34:53  profilanswer
 

Les pointeurs intelligents deviennent utiles dès que y'a un deuxième new dans le constructeur, car si y'a eu un new ok et que les autres echouent hop fuite de mémoire (exception dans le ctor => destructeur pas appelé).
 
Un bouquin c'est bien, mais je te conseille aussi de lire 2 ou 3 FAQ. C'est hallucinant le temps que tu gagnes à commencer par étudier une FAQ quand tu te mets à un langage.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
mood
Publicité
Posté le 02-02-2005 à 22:34:53  profilanswer
 

n°970010
++fab
victime du syndrome IH
Posté le 02-02-2005 à 22:49:02  profilanswer
 

HelloWorld a écrit :

Les pointeurs intelligents deviennent utiles dès que y'a un deuxième new dans le constructeur, car si y'a eu un new ok et que les autres echouent hop fuite de mémoire (exception dans le ctor => destructeur pas appelé).


 
On peut aussi utiliser new(nothrow), et tester si le pointeur est nul en cas d'échec.
Comme pointeur intelligent, le auto_ptr<> doit pouvoir suffire.

n°970015
HelloWorld
Salut tout le monde!
Posté le 02-02-2005 à 22:53:16  profilanswer
 

Et tu fais quoi si le new(nothrow) échoue ? Tu lances ti même bad_alloc plus tard :/
http://www.gotw.ca/publications/mill16.htm
auto_ptr il est bien pour ça oui, sauf qi tu as alloué un tableau (new []).


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°970037
++fab
victime du syndrome IH
Posté le 02-02-2005 à 23:05:03  profilanswer
 

HelloWorld a écrit :

Et tu fais quoi si le new(nothrow) échoue ? Tu lances ti même bad_alloc plus tard :/
http://www.gotw.ca/publications/mill16.htm
auto_ptr il est bien pour ça oui, sauf qi tu as alloué un tableau (new []).


 
ba tu libère tout à la mimine :o
ça revient au meme que si tu faisais un bloc try{...} catch(bad_alloc) pour chaque new.
Et non pas un pour tous, genre

Code :
  1. try
  2. {
  3.     a = new Foo;
  4.     b = new Bar;
  5. }
  6. catch(bad_alloc)
  7. {
  8.     //bien emmerdé pour deleter ... ->pointeur à 0, et compter sur delete
  9. }


Message édité par ++fab le 02-02-2005 à 23:05:25
n°970121
smag
Posté le 03-02-2005 à 00:18:19  profilanswer
 

++fab a écrit :

ba tu libère tout à la mimine :o
ça revient au meme que si tu faisais un bloc try{...} catch(bad_alloc) pour chaque new.
Et non pas un pour tous, genre

Code :
  1. try
  2. {
  3.     a = new Foo;
  4.     b = new Bar;
  5. }
  6. catch(bad_alloc)
  7. {
  8.     //bien emmerdé pour deleter ... ->pointeur à 0, et compter sur delete
  9. }



ça c le dernier chapitre de mon bouquin!!
 
Que me conseillez vous pour continuer de découvrir ce langage?
des titres de bouquins? des exos? des sites? des tutoriels?

n°970154
++fab
victime du syndrome IH
Posté le 03-02-2005 à 00:51:30  profilanswer
 

smag a écrit :

ça c le dernier chapitre de mon bouquin!!
 
Que me conseillez vous pour continuer de découvrir ce langage?
des titres de bouquins? des exos? des sites? des tutoriels?


 
je te conseille "le petit stroustrup illustré" :D

n°970170
HelloWorld
Salut tout le monde!
Posté le 03-02-2005 à 01:22:01  profilanswer
 

++fab a écrit :

ba tu libère tout à la mimine :o
ça revient au meme que si tu faisais un bloc try{...} catch(bad_alloc) pour chaque new.
Et non pas un pour tous, genre

Code :
  1. try
  2. {
  3.     a = new Foo;
  4.     b = new Bar;
  5. }
  6. catch(bad_alloc)
  7. {
  8.     //bien emmerdé pour deleter ... ->pointeur à 0, et compter sur delete
  9. }



C'est pas de ça que je voulais parler, mais du fait que après avoir rendu le code exception safe, il fallait bien relancer l'exception pour indiquer l'echec du ctor. Dans le cas d'un try...catch tu relances avec throw;, avec new(nothrow) c'est toi qui fait le throw... Je trouve ça moyen de dire
"Toi fait cette opération sans lever d'exception, si tu échoues, je lève l'exception que tu aurais du lever"
Surtout que y'a pas que bad_alloc de possible, le ctor de l'objet alloué peut très bien lever autre chose, et malgré ton nothrow tu te prend un exception dans la tête.

Code :
  1. class Test
  2. {
  3. public:
  4.     Test()
  5.     {
  6.         throw "dtc";   
  7.     }       
  8. };
  9.    
  10. int main()
  11. {
  12.     try
  13.     {
  14.         Test * t = new(nothrow) Test;
  15.     }
  16.     catch ( const char * e )   
  17.     {
  18.         cerr << e << '\n'; 
  19.     }
  20. }


 
Typiquement avec try...catch c'est lourd oui

Code :
  1. Test::Test():
  2.     a(0), b(0)
  3. {
  4.     try
  5.     {
  6.         a = new Foo;
  7.         b = new Bar;
  8.     }
  9.     catch ( ... )
  10.     {
  11.         delete b;
  12.         delete a;
  13.         throw; // relancer
  14.     }
  15. }
  16. Test::~Test()
  17. {
  18.     delete b;
  19.     delete a;
  20. }


 
et donc vive les smart ptr, ça devient tout propre et simple

Code :
  1. Test::Test()
  2. {
  3.     a = std::auto_ptr<Foo>( new Foo );
  4.     b = std::auto_ptr<Bar>( new Bar );
  5. }
  6. // plus besoin du destructeur


 
Ce principe c'est le RAII, l'essayer c'est l'adopter :love:


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°970254
Taz
bisounours-codeur
Posté le 03-02-2005 à 10:09:26  profilanswer
 

c'est le principe du bloc try_catch fonctionnel :o

n°970455
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 03-02-2005 à 12:58:55  profilanswer
 

pour la définition du constructeur de copie, y'a un topic
http://forum.hardware.fr/forum2.ph [...] 0&subcat=0

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
Comparatif sur l'interet des languages de progDev-Cpp
changer de user durant l'execution d'un script[Débutant] pb execution java script
Temps d'éxécution comparable?temps d'exécution en millisecondes?
cryptage en CPPprobleme dev-C++
verification prog C++ 
Plus de sujets relatifs à : pb àl'execution car prog trop gros pour DEV-CPP


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)