IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Exceptions et boule de gomme


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut Exceptions et boule de gomme
    Bonjour à tou(te)s !

    en faisant joujou avec les exceptions sous gcc, je suis tombé sur un comportement des plus étranges...
    Voici un petit bout de code pour illustrer mon propos :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    #include <iostream>
    #include <string>
    using namespace std ;
     
    struct Exception
        {
        Exception ()                                               { cout << "Exception::Exception()" << endl ;}
        Exception ( const Exception & e )     : message(e.message) { cout << "Exception::Exception(e) " << message << endl ;}
        Exception ( const string & m )        : message(m)         { cout << "Exception::Exception(s) " << message << endl ;}
        string message ;
        };
     
    void failure1 ( const string & s )
        {
        cout << "failure1 : just before throw " << s << endl ; 
        throw Exception( s ) ; // throw just constructed Exception : ok
        }
     
    void failure2 ( const string & s )
        {
        static Exception e ;
        e.message = s ;
        cout << "failure2 : just before throw " << s << endl ; 
        throw e ; // throw static Exception : ok
        }
     
    void failure3 ( const string & s )
        {
        Exception e( s ) ;
        cout << "failure3 : just before throw " << s << endl ; 
        throw e ; // throw local Exception : KO
        }
     
    void sub_failure4 ( const Exception & exception )
        {
        cout << "sub_failure4 : just before throw " << exception.message << endl ; 
        throw Exception( exception ) ; // throw just constructed Exception, but from elder one : KO
        }
     
    void failure4 ( const string & message )    
        { 
        cout << "failure4 : just before call sub_failure4" << endl ; 
        sub_failure4( Exception( message )) ;
        }
     
    int main ( int argc , const char ** argv )
        {
        try { throw Exception("Exception 0") ;} catch ( Exception e )  { cout << "catch : " << e.message << endl << endl ;} // ok
        try { failure1("Exception 1" )       ;} catch ( Exception e )  { cout << "catch : " << e.message << endl << endl ;} // ok
        try { failure2("Exception 2" )       ;} catch ( Exception e )  { cout << "catch : " << e.message << endl << endl ;} // ok
        if (argc > 1)
        try { failure3("Exception 3" )       ;} catch ( Exception e )  { cout << "catch : " << e.message << endl << endl ;} // KO !
        try { failure4("Exception 4" )       ;} catch ( Exception e )  { cout << "catch : " << e.message << endl << endl ;} // KO !
        }
    J'ai 5 scénarios de levée d'exception : les 0, 1 et 2 fonctionnent, les 3 et 4 plantent !
    NB : pour pouvoir tester facilement les 3 et 4, je les ai conditionné par la présence d'un argument sur la ligne de commande.

    Compilation (avec gcc (i686-posix-dwarf-rev2, Built by MinGW-W64 project) 4.9.0 sous Windows 7 64bits) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc e.cpp -Wall -fexceptions -O2 -lstdc++ -o e.exe
    Exécution avec l'exception n°4 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    >e.exe
    Exception::Exception(s) Exception 0
    Exception::Exception(e) Exception 0
    catch : Exception 0
     
    failure1 : just before throw Exception 1
    Exception::Exception(s) Exception 1
    Exception::Exception(e) Exception 1
    catch : Exception 1
     
    Exception::Exception()
    failure2 : just before throw Exception 2
    Exception::Exception(e) Exception 2
    Exception::Exception(e) Exception 2
    catch : Exception 2
     
    failure4 : just before call sub_failure4
    Exception::Exception(s) Exception 4
    sub_failure4 : just before throw Exception 4
    Exception::Exception(e) Exception 4
     
    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information.
    Exécution avec l'exception n°3 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    e.exe x
    Exception::Exception(s) Exception 0
    Exception::Exception(e) Exception 0
    catch : Exception 0
     
    failure1 : just before throw Exception 1
    Exception::Exception(s) Exception 1
    Exception::Exception(e) Exception 1
    catch : Exception 1
     
    Exception::Exception()
    failure2 : just before throw Exception 2
    Exception::Exception(e) Exception 2
    Exception::Exception(e) Exception 2
    catch : Exception 2
     
    Exception::Exception(s) Exception 3
    failure3 : just before throw Exception 3
    Exception::Exception(e) Exception 3
     
    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information.
    Comme on peut le voir, dans les cas 3 et 4, on n'atteint pas le catch.

    Si quelqu'un(e) comprend quelque chose à ce mystère, je suis preneur !

    Merci d'avance

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    À vue de pif cela semble logique :

    Exception 3 -> Lancement d'une exception qui est détruite à la fermeture de failure3. Comportement normal pour une variable locale.

    Exception 4 -> Tu dois avoir un problème avec ton constructeur de recopie, puisque ton paramètre doit être détruit à la fermeture de sub_failure4.

  3. #3
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par foetus Voir le message
    À vue de pif cela semble logique :

    Exception 3 -> Lancement d'une exception qui est détruite à la fermeture de failure3. Comportement normal pour une variable locale.
    Mais les exceptions sont censées être lancées par valeur, non?
    (surtout qu'ici en plus, elles sont aussi catchées par valeur)


    Un truc qui serait intéressant serait de rajouter un destructeur à tes exceptions, pour voir quand exactement elles sont détruites.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre chevronné Avatar de Gaulouis
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2015
    Messages
    252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2015
    Messages : 252
    Par défaut Pour info
    Salut, j'ai fait un petit test sur Windows 7 32bits(gcc 4.9.1) et sur Ubuntu 64bits (gcc 4.8.4) y'a rien qui plante chez moi

  5. #5
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Pareil que Gaulouis avec gcc et g++ 4.9.1 et 5.0.0 sur Linux.

  6. #6
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    Merci les gars !

    Donc si je comprends bien, c'est juste ma config et un léger bug de gcc qui sont en cause...

  7. #7
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    Punaise ! je suis passé à gcc (x86_64-posix-seh-rev2, Built by MinGW-W64 project) 4.9.0 et tout passe !

    Toutefois, je me pose encore des questions à propos de la durée de vie d'une variable levée comme exception...
    J'ai donc codé une variante de mon test précédant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    #include <iostream>
    #include <string>
    using namespace std ;
     
    struct Exception
        {
       ~Exception ()                                                         { cout << "~Exception[" << id << "]()" << endl ;}
        Exception ()                          : id(bid++)                    { cout <<  "Exception[" << id << "]()" << endl ;}
        Exception ( const Exception & e )     : id(bid++),message(e.message) { cout <<  "Exception[" << id << "]([" << e.id << "])" << endl ;}
        Exception ( const string & m )        : id(bid++),message(m)         { cout <<  "Exception[" << id << "]('" << message << "')" << endl ;}
        Exception & set ( const string & m )                                 { message = m ; cout <<  "Exception[" << id << "] = " << message << endl ; return *this ;}
        static int bid ;
        int    id ;
        string message ;
        };
     
    int Exception::bid = 1 ;
     
    void failure1 ( const string & s )
        {
        cout << "failure1 : just before throw " << s << endl ; 
        throw Exception( s ) ;
        }
     
    void failure2 ( const string & s )
        {
        static Exception e ;
        e.set( s ) ;
        cout << "failure2 : just before throw " << s << endl ; 
        throw e ;
        }
     
    void sub_failure3 ( const Exception & exception )
        {
        cout << "sub_failure3 : just before throw " << exception.message << endl ; 
        throw exception ;
        }
     
    void failure3 ( const string & message )    
        { 
        cout << "failure3 : just before call sub_failure3" << endl ; 
        sub_failure3( Exception( message )) ;
        }
     
    int main ()
        {
        try { failure1("***1***" ) ;} catch ( Exception e )          { cout << "catch[" << e.id << "]" << endl ;} ; cout << "---------------------------" << endl ;
        try { failure1("***2***" ) ;} catch ( Exception & e )        { cout << "catch[" << e.id << "]" << endl ;} ; cout << "---------------------------" << endl ;
        try { failure1("***3***" ) ;} catch ( const Exception & e )  { cout << "catch[" << e.id << "]" << endl ;} ; cout << "---------------------------" << endl ;
        try { failure2("***4***" ) ;} catch ( const Exception & e )  { cout << "catch[" << e.id << "]" << endl ;} ; cout << "---------------------------" << endl ;
        try { failure3("***5***" ) ;} catch ( const Exception & e )  { cout << "catch[" << e.id << "]" << endl ;} ; cout << "---------------------------" << endl ;
        }
    et sa sortie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    failure1 : just before throw ***1***
    Exception[1]('***1***')
    Exception[2]([1])
    catch[2]
    ~Exception[2]()
    ~Exception[1]()
    ---------------------------
    failure1 : just before throw ***2***
    Exception[3]('***2***')
    catch[3]
    ~Exception[3]()
    ---------------------------
    failure1 : just before throw ***3***
    Exception[4]('***3***')
    catch[4]
    ~Exception[4]()
    ---------------------------
    Exception[5]()
    Exception[5] = ***4***
    failure2 : just before throw ***4***
    Exception[6]([5])
    catch[6]
    ~Exception[6]()
    ---------------------------
    failure3 : just before call sub_failure3
    Exception[7]('***5***')
    sub_failure3 : just before throw ***5***
    Exception[8]([7])
    ~Exception[7]()
    catch[8]
    ~Exception[8]()
    ---------------------------
    ~Exception[5]()
    De 1,2,3 : on voit qu'on économise une construction par copie en catchant l’exception par référence.
    De 4 : il construit quand même une copie pour éviter de lever une exception statique (on se demande pourquoi...).
    De 5 : il y a une construction par copie en trop selon moi...

    Si quelqu'un a un avis pertinent...

Discussions similaires

  1. Question et boule de gomme
    Par said0011 dans le forum Débuter
    Réponses: 1
    Dernier message: 06/11/2007, 19h13
  2. [ActionListener] mystère et boule de gomme
    Par jcodeunpeu dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 23/12/2005, 22h09
  3. Réponses: 3
    Dernier message: 01/11/2002, 14h30
  4. Réponses: 5
    Dernier message: 12/06/2002, 15h12
  5. c: gestion des exceptions
    Par vince_lille dans le forum C
    Réponses: 7
    Dernier message: 05/06/2002, 14h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo