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

Langage C++ Discussion :

La malédiction du GOTO


Sujet :

Langage C++

  1. #1
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2007
    Messages : 204
    Points : 89
    Points
    89
    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 : 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
    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 éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    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.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2007
    Messages : 204
    Points : 89
    Points
    89
    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
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    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
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 5 463
    Points : 16 213
    Points
    16 213
    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.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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 895
    Points : 4 551
    Points
    4 551
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    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.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par Emmanuel Deloget Voir le message
    Ah bon ? Je ne savais pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 régulier
    Profil pro
    Étudiant
    Inscrit en
    Juin 2007
    Messages
    204
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2007
    Messages : 204
    Points : 89
    Points
    89
    Par défaut
    Merci pour vos réponses, je passe le post en résolu

  10. #10
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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 895
    Points : 4 551
    Points
    4 551
    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
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    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
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 5 463
    Points : 16 213
    Points
    16 213
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    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
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    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 éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    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.

Discussions similaires

  1. Pourquoi "goto" est déconseillé ?
    Par Melchisedec dans le forum Débuter
    Réponses: 20
    Dernier message: 30/05/2020, 16h24
  2. [DOS] goto inattendu
    Par isidore dans le forum Scripts/Batch
    Réponses: 6
    Dernier message: 26/11/2009, 00h06
  3. traduction de GoTo et GoSub en ASP
    Par can dans le forum ASP
    Réponses: 1
    Dernier message: 23/08/2005, 10h14
  4. [FLASH MX2004] - Fonction GOTO...
    Par Neutrino- dans le forum Flash
    Réponses: 3
    Dernier message: 12/05/2005, 00h29
  5. [langage] Pb de syntaxe avec GOTO
    Par BEAUJAULT dans le forum Langage
    Réponses: 2
    Dernier message: 14/10/2004, 16h02

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