Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 15 sur 15
  1. #1
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 27
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2007
    Messages : 204
    Points : 58
    Points
    58

    Par défaut La malédiction du GOTO

    Bonjour à tous !

    Alors tout d'abord, je sais très bien que GOTO c'est le diable incarné sous forme de spaghettis maléfiques et je ne m'en suis jamais servit

    ...MAIS...

    J'aimerais savoir comment faire l'équivalent du code ci-dessous.
    Comment rediriger vers une zone où je vais delete tous les variables créées avec new, fermer tous les fichiers ouverts, close tous les handle de windows, etc, pour chaque erreur rencontrée.
    Tout ceci pour justement éviter de mettre 10 lignes de suppression de variables, etc... à chaque erreur rencontrée.

    Exemple :
    Code :
    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
    int main(int argc, char* argv[])
    {
    	char* test1 = NULL;
    	char* test2 = NULL;
    	char* test3 = NULL;
    	FILE* file1 = NULL;
    	FILE* file2 = NULL;
     
    	test1 = new char[argc*15];
    	test2 = new char[argc*37];
    	test3 = new char[argc*66];
     
    	f1 = fopen("C:\\Test.txt", "rb");
    	f2 = fopen("C:\\Tset.txt", "rb");
     
    	if( !1=1 ) goto cleanup;
    	else
    	{
    		// Do Something
    	}
    	if( !2=2 ) goto cleanup;
    	else
    	{
    		// Do Something
    	}
    	if( !3=3 ) goto cleanup;
    	else
    	{
    		// Do Something
    	}
    	if( !3=3 ) goto cleanup;
    	else
    	{
    		// Do Something
    	}
     
    	cleanup:
    	if(test1) delete[] test1;
    	if(test2) delete[] test2;
    	if(test3) delete[] test3;
    	if(f1) fclose(f1);
    	if(f2) fclose(f2);
     
    	return 0;
    }
    Ceci est un exemple bête et méchant, mais actuellement et sans Goto, à chaque fois qu'une condition n'est pas remplie, je fait tous les delete nécessaires + return.

    Du coup, si j'ai beaucoup de variables, fichiers ouverts, etc, dans une méthode, sa m'arrive de mettre beaucoup de lignes de cleanup à chaque fois et souvent les mêmes.

    Une autre solution serait de faire plein de if/else imbriqués, mais je vous raconte pas le bordel s'il y en a beaucoup.

    Des idées? Ou peut être que le goto est "acceptable" dans ce genre de situations?

    Merci d'avance,
    Clément.

  2. #2
    Expert Confirmé Sénior

    Homme Profil pro Pierre
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    2 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Pierre
    Localisation : France

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

    Informations forums :
    Inscription : juin 2007
    Messages : 2 188
    Points : 5 070
    Points
    5 070

    Par défaut

    Tu as l'exacte réponse dans ce tuto

    Merci à Alexandre Laurent pour l'avoir écrit.

    Puisque tu es en C++, utilise les classes et la fonction magique dont chacune dispose: son destructeur

    Le RAII utilise cela pour nettoyer automatiquement toute ressource.
    L'idée est d'obtenir un pointeur/fichier/socket/troll à deux têtes dans le constructeur, et de le libérer dans le destructeur.

    À l'usage, le simple fait de déclarer/initialiser une variable, la ressource est acquise.
    Si l'acquisition est réussie, la variable sera détruite en sortant de sa portée, et donc la ressource libérée, sans aucun traitement particulier
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • La plus sotte des questions est celle qu'on ne pose pas.

    Pour faire des graphes, essayez yEd.

  3. #3
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 27
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2007
    Messages : 204
    Points : 58
    Points
    58

    Par défaut

    Ok, Merci pour ta réponse.

    J'avais déjà lu quelques trucs sur le RAII. En gros le RAII c'est les shared_ptr c'est ça?

  4. #4
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 743
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 743
    Points : 17 226
    Points
    17 226

    Par défaut

    Citation Envoyé par CleeM Voir le message
    Ok, Merci pour ta réponse.

    J'avais déjà lu quelques trucs sur le RAII. En gros le RAII c'est les shared_ptr c'est ça?
    En fait, RAII, c'est un concept, très mal nommé au demeurant...

    Cela signifie en anglais Ressource Aquisition Is Initialization (ou, si tu préfères en français: l'acquisition de ressources est initialisation).

    Ce qui nous intéresse en fait surtout (ce qui justifie ma remarque sur le "très mal nommé" ), c'est justement à l'effet inverse : le fait que, quand on détruit une variable, toutes les ressources qu'elle contient soient elles aussi correctement détruites

    Les shared_ptr sont une manière parmi d'autres de mettre ce concept en pratique.

    Tu peux très bien envisager de gérer toi meme correctement les ressources à la main, mais il est vrai que les pointeurs intelligents (car il n'y a pas que shared_ptr ) apportent une facilité certaine dans cette optique
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro Loïc Joly
    Développeur informatique
    Inscrit en
    août 2004
    Messages
    4 984
    Détails du profil
    Informations personnelles :
    Nom : Homme Loïc Joly
    Âge : 40
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : août 2004
    Messages : 4 984
    Points : 12 149
    Points
    12 149

    Par défaut

    Citation Envoyé par CleeM Voir le message
    En gros le RAII c'est les shared_ptr c'est ça?
    Dans ton cas, le RAII, c'est surtout std::string pour gérer les chaînes de caractère, et [i/o]fstream pour lire les fichiers.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Et celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

  6. #6
    Expert Confirmé Sénior

    Homme Profil pro Emmanuel Deloget
    Développeur informatique
    Inscrit en
    septembre 2007
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Nom : Homme Emmanuel Deloget
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : septembre 2007
    Messages : 1 894
    Points : 4 451
    Points
    4 451

    Par défaut

    Citation Envoyé par CleeM Voir le message
    je sais très bien que GOTO c'est le diable incarné sous forme de spaghettis maléfiques et je ne m'en suis jamais servit.
    Ah bon ? Je ne savais pas.

    Code :
    1
    2
    3
    4
     
    $ cd linux-2.6.30
    $ grep goto -rHn | wc -l
    68703
    Il faudra penser à le dire au développeurs du kernel Linux, parce qu'il semblerait bien qu'il l'utilise un peu
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Expert Confirmé Sénior

    Homme Profil pro Pierre
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    2 188
    Détails du profil
    Informations personnelles :
    Nom : Homme Pierre
    Localisation : France

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

    Informations forums :
    Inscription : juin 2007
    Messages : 2 188
    Points : 5 070
    Points
    5 070

    Par défaut

    En C++, on ne devrait pas l'utiliser, parce qu'on dispose du RAII.

    En C, c'est une toute autre histoire, et le goto peut être intéressant, quoique je m'en soit toujours passé.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • La plus sotte des questions est celle qu'on ne pose pas.

    Pour faire des graphes, essayez yEd.

  8. #8
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 743
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 743
    Points : 17 226
    Points
    17 226

    Par défaut

    Salut,
    Citation Envoyé par Emmanuel Deloget Voir le message
    Ah bon ? Je ne savais pas.

    Code :
    1
    2
    3
    4
     
    $ cd linux-2.6.30
    $ grep goto -rHn | wc -l
    68703
    Il faudra penser à le dire au développeurs du kernel Linux, parce qu'il semblerait bien qu'il l'utilise un peu
    A vrai dire, je n'ai jamais utilisé un seul goto, meme en C

    Faut dire que, quand un prof qui fait une fois et demie ton poids te menace de te faire passer par la fenetre si tu l'utilises, ca te fait réfléchir

    Mais il est vrai que je n'ai jamais codé de kernel linux non plus

    A décharge des développeurs du kernel:
    1. Je me demande combien de ces goto peuvent être des reliquats du kernel original ou d'une époque où on trouvait l'utilisation du goto "naturelle"
    2. Dans certaines situations (surtout en C, ou la notion de RAII est difficilement applicable ) je peux concevoir que l'utilisation de goto peut être une solution "bien moins mauvaise" que celle d'imbriquer 15 if les uns dans les autres pour éviter d'avoir à l'utiliser.

    Mais cela n'empêche que, à choisir, je préfères aussi l'éviter autant que faire se peut, à moins que cela ne représente vraiment la moins mauvaise solution
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 27
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : juin 2007
    Messages : 204
    Points : 58
    Points
    58

    Par défaut

    Merci pour vos réponses, je passe le post en résolu

  10. #10
    Expert Confirmé Sénior

    Homme Profil pro Emmanuel Deloget
    Développeur informatique
    Inscrit en
    septembre 2007
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Nom : Homme Emmanuel Deloget
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : septembre 2007
    Messages : 1 894
    Points : 4 451
    Points
    4 451

    Par défaut

    Citation Envoyé par koala01 Voir le message
    Salut,
    A vrai dire, je n'ai jamais utilisé un seul goto, meme en C

    Faut dire que, quand un prof qui fait une fois et demie ton poids te menace de te faire passer par la fenetre si tu l'utilises, ca te fait réfléchir

    Mais il est vrai que je n'ai jamais codé de kernel linux non plus

    A décharge des développeurs du kernel:
    1. Je me demande combien de ces goto peuvent être des reliquats du kernel original ou d'une époque où on trouvait l'utilisation du goto "naturelle"
    2. Dans certaines situations (surtout en C, ou la notion de RAII est difficilement applicable ) je peux concevoir que l'utilisation de goto peut être une solution "bien moins mauvaise" que celle d'imbriquer 15 if les uns dans les autres pour éviter d'avoir à l'utiliser.

    Mais cela n'empêche que, à choisir, je préfères aussi l'éviter autant que faire se peut, à moins que cela ne représente vraiment la moins mauvaise solution
    C'est surtout "ne pas imbriquer 15 if" qui fait qu'il y a tant de goto dans le kernel. Le code reste simple à lire et à débugger - la condition, bien évidemment, c'est de l'utiliser correctement : comme tout outil dangereux, une utilisation idiote va plus que probablement ruiner les utilisations correctes. Donc : pas de saut dans des boucles, pas de saut backward (s'il y en a, ce sont des exceptions qui ont été apprement discutées), etc.

    Le fait est que goto est dangereux si on l'utilise mal. Mais correctement utilisé (en C, bien sûr ; C++ a RAII et ça permet d'éviter toute utilisation de goto), c'est un outil puissant qui simplifie le code avec un coût extrèmement faible au runtime (puisque dans la grande majorité des cas, c'est juste un jump conditionnel).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  11. #11
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 743
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 743
    Points : 17 226
    Points
    17 226

    Par défaut

    Citation Envoyé par Emmanuel Deloget Voir le message
    C'est surtout "ne pas imbriquer 15 if" qui fait qu'il y a tant de goto dans le kernel. Le code reste simple à lire et à débugger - la condition, bien évidemment, c'est de l'utiliser correctement : comme tout outil dangereux, une utilisation idiote va plus que probablement ruiner les utilisations correctes. Donc : pas de saut dans des boucles, pas de saut backward (s'il y en a, ce sont des exceptions qui ont été apprement discutées), etc.
    Cela parrait clair, en tout cas, ce l'était pour moi
    Le fait est que goto est dangereux si on l'utilise mal. Mais correctement utilisé (en C, bien sûr ; C++ a RAII et ça permet d'éviter toute utilisation de goto), c'est un outil puissant qui simplifie le code avec un coût extrèmement faible au runtime (puisque dans la grande majorité des cas, c'est juste un jump conditionnel).
    C'est bien pour cela que je ne suis pas opposé à son usage, mais que je préfères à strictement bon escient

    Mais j'avais déjà émis cet opinion, il y a bien longtemps, je ne fais que me répéter ici
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro Loïc Joly
    Développeur informatique
    Inscrit en
    août 2004
    Messages
    4 984
    Détails du profil
    Informations personnelles :
    Nom : Homme Loïc Joly
    Âge : 40
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : août 2004
    Messages : 4 984
    Points : 12 149
    Points
    12 149

    Par défaut

    Je tiens juste à préciser qu'en plus d'être moins utile en C++ qu'en C, le goto est aussi plus dangereux à utiliser en C++. Exemple :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int i = f();
    if (i<0)
    {
      goto end;
    }
     
    string s = "Hello ";
    cout << s << i;
     
    end:
      // Do cleanup
    Ce code est invalide en C++.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Et celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

  13. #13
    Expert Confirmé Sénior

    Inscrit en
    novembre 2005
    Messages
    5 103
    Détails du profil
    Informations forums :
    Inscription : novembre 2005
    Messages : 5 103
    Points : 6 707
    Points
    6 707

    Par défaut

    Citation Envoyé par koala01 Voir le message
    A décharge des développeurs du kernel:
    1. Je me demande combien de ces goto peuvent être des reliquats du kernel original ou d'une époque où on trouvait l'utilisation du goto "naturelle"
    Non.

    Goto considered harmfull, Dijkstra, 1968.

    Linus Benedict Torvalds, né le 28 décembre 1969.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  14. #14
    Modérateur
    Avatar de koala01
    Profil pro Philippe Dunski
    Inscrit en
    octobre 2004
    Messages
    9 743
    Détails du profil
    Informations personnelles :
    Nom : Philippe Dunski
    Âge : 42

    Informations forums :
    Inscription : octobre 2004
    Messages : 9 743
    Points : 17 226
    Points
    17 226

    Par défaut

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Non.

    Goto considered harmfull, Dijkstra, 1968.

    Linus Benedict Torvalds, né le 28 décembre 1969.
    Et combien de codes furent écrits entre 1968 et, mettons, les années 90, sans tenir compte de cet excellent conseil

    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  15. #15
    Expert Confirmé Sénior

    Inscrit en
    novembre 2005
    Messages
    5 103
    Détails du profil
    Informations forums :
    Inscription : novembre 2005
    Messages : 5 103
    Points : 6 707
    Points
    6 707

    Par défaut

    Citation Envoyé par koala01 Voir le message
    Et combien de codes furent écrits entre 1968 et, mettons, les années 90, sans tenir compte de cet excellent conseil

    Depuis lors, l'utilisation non structurée du goto n'est plus en odeur de sainteté nulle part. Les langages ont acquis les structures de contrôle permettant de s'en passer (comparer sur ce point FORTRAN 66 et FORTRAN 77 par exemple) et le seul point réellement discuté, c'est de savoir si elles suffisent et que tout usage doit être prohibé ou s'il y a encore une place pour certains cas mal gérés par les structures classiques. L'utilisation dans Linux relève de cette dernière opinion.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •