Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Langage
Langage Langage C++, Programmation Orientée Objet, Templates, etc. Avant de poster : FAQ C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 06/12/2012, 15h46   #1
CleeM
Membre du Club
 
Étudiant
Inscription : juin 2007
Messages : 204
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Gard (Languedoc Roussillon)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2007
Messages : 204
Points : 59
Points : 59
Envoyer un message via MSN à CleeM
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.
CleeM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2012, 16h11   #2
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 185
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 : 1 185
Points : 2 502
Points : 2 502
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.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2012, 16h34   #3
CleeM
Membre du Club
 
Étudiant
Inscription : juin 2007
Messages : 204
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Gard (Languedoc Roussillon)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2007
Messages : 204
Points : 59
Points : 59
Envoyer un message via MSN à CleeM
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?
CleeM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/12/2012, 19h21   #4
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 613
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 613
Points : 13 289
Points : 13 289
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/12/2012, 01h33   #5
JolyLoic
Rédacteur/Modérateur
 
Avatar de JolyLoic
 
Homme Loïc Joly
Développeur informatique
Inscription : août 2004
Messages : 4 675
Détails du profil
Informations personnelles :
Nom : Homme Loïc Joly
Âge : 38
Localisation : France

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

Informations forums :
Inscription : août 2004
Messages : 4 675
Points : 9 897
Points : 9 897
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.
JolyLoic est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 10h56   #6
Emmanuel Deloget
Expert Confirmé Sénior
 
Homme Emmanuel Deloget
Développeur informatique
Inscription : septembre 2007
Messages : 1 826
Détails du profil
Informations personnelles :
Nom : Homme Emmanuel Deloget
Âge : 37
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 826
Points : 4 381
Points : 4 381
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.
Emmanuel Deloget est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/12/2012, 12h51   #7
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 185
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 : 1 185
Points : 2 502
Points : 2 502
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.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/12/2012, 15h50   #8
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 613
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 613
Points : 13 289
Points : 13 289
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 18h01   #9
CleeM
Membre du Club
 
Étudiant
Inscription : juin 2007
Messages : 204
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Gard (Languedoc Roussillon)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2007
Messages : 204
Points : 59
Points : 59
Envoyer un message via MSN à CleeM
Merci pour vos réponses, je passe le post en résolu
CleeM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 20h34   #10
Emmanuel Deloget
Expert Confirmé Sénior
 
Homme Emmanuel Deloget
Développeur informatique
Inscription : septembre 2007
Messages : 1 826
Détails du profil
Informations personnelles :
Nom : Homme Emmanuel Deloget
Âge : 37
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 826
Points : 4 381
Points : 4 381
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.
Emmanuel Deloget est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 07/12/2012, 20h45   #11
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 613
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 613
Points : 13 289
Points : 13 289
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
Citation:
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/12/2012, 21h40   #12
JolyLoic
Rédacteur/Modérateur
 
Avatar de JolyLoic
 
Homme Loïc Joly
Développeur informatique
Inscription : août 2004
Messages : 4 675
Détails du profil
Informations personnelles :
Nom : Homme Loïc Joly
Âge : 38
Localisation : France

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

Informations forums :
Inscription : août 2004
Messages : 4 675
Points : 9 897
Points : 9 897
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.
JolyLoic est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2012, 17h14   #13
Jean-Marc.Bourguet
Expert Confirmé Sénior

 
Inscription : novembre 2005
Messages : 4 970
Détails du profil
Informations forums :
Inscription : novembre 2005
Messages : 4 970
Points : 5 607
Points : 5 607
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.
Jean-Marc.Bourguet est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 09/12/2012, 20h06   #14
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 613
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 613
Points : 13 289
Points : 13 289
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2012, 21h04   #15
Jean-Marc.Bourguet
Expert Confirmé Sénior

 
Inscription : novembre 2005
Messages : 4 970
Détails du profil
Informations forums :
Inscription : novembre 2005
Messages : 4 970
Points : 5 607
Points : 5 607
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.
Jean-Marc.Bourguet est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 11h30.


 
 
 
 
Partenaires

Hébergement Web