Je comprends cela, sauf pour rompre les boucles imbriquées dans des boucles; la goto
déclaration est éludée et critiquée comme un style de programmation sujette aux bogues, pour ne jamais être utilisée.
Alt Text: "Neal Stephenson trouve ça mignon de nommer son label" dengo ""
Voir la bande dessinée originale à l' adresse : http://xkcd.com/292/
Parce que j'ai appris cela tôt; Je n'ai vraiment aucune idée ou expérience des types de bugs goto
qui y conduisent. Alors de quoi parle-t-on ici:
- Instabilité?
- Code intempestif ou illisible?
- Des vulnérabilités de sécurité?
- Quelque chose d'autre entièrement?
À quel type de bogues les déclarations "goto" conduisent-elles réellement? Existe-t-il des exemples historiquement significatifs?
Réponses:
Voici une façon de regarder ce que je n'ai pas encore vu dans les autres réponses.
C'est à propos de la portée. L'un des principaux piliers d'une bonne pratique de programmation consiste à garder votre champ d'activité étroit. Vous avez besoin d'une marge de manœuvre étroite, car vous n'avez pas la capacité mentale de superviser et de comprendre plus que quelques étapes logiques. Vous créez donc de petits blocs (qui deviennent chacun "une chose"), puis vous construisez avec ceux-ci pour créer des blocs plus grands qui deviennent une seule chose, etc. Cela permet de garder les choses gérables et compréhensibles.
Un goto gonfle efficacement la portée de votre logique à l'ensemble du programme. Ceci est sûr de vaincre votre cerveau pour tous les programmes, même les plus petits, ne couvrant que quelques lignes.
Vous ne pourrez donc plus savoir si vous avez commis une erreur, car il y a trop à prendre et à vérifier votre pauvre petite tête. C'est le vrai problème, les bugs ne sont qu'un résultat probable.
la source
Ce n'est pas que le
goto
soit mauvais en soi. (Après tout, chaque instruction de saut dans un ordinateur est un goto.) Le problème est qu’il existe un style humain de programmation qui précède la programmation structurée, ce que l’on pourrait appeler une programmation en "organigramme".Dans la programmation par organigramme (que les gens de ma génération ont apprise et qui a été utilisée pour le programme Apollo Moon), vous créez un diagramme avec des blocs pour l'exécution des instructions et des diamants pour les décisions, et vous pouvez les relier avec des lignes qui vont partout. (Ce qu'on appelle "code spaghetti".)
Le problème avec le code spaghetti est que vous, le programmeur, pourriez "savoir" que c'était juste, mais comment pourriez-vous le prouver , à vous-même ou à quelqu'un d'autre? En fait, cela pourrait en réalité avoir une mauvaise conduite, et votre connaissance que c'est toujours correct pourrait être fausse.
Vient ensuite la programmation structurée avec des blocs de début à la fin, pour, tandis que, si-sinon, et ainsi de suite. Ceux-ci avaient l'avantage que vous pouviez toujours faire quelque chose, mais si vous faisiez attention, vous pouvez être sûr que votre code est correct.
Bien sûr, les gens peuvent toujours écrire du code spaghetti même sans
goto
. La méthode courante consiste à écrire unwhile(...) switch( iState ){...
, où différents cas définissent leiState
sur différentes valeurs. En fait, en C ou C ++, on pourrait écrire une macro pour le faire, et le nommerGOTO
, de sorte que dire que vous n'utilisez pasgoto
est une distinction sans différence.Comme exemple de la façon dont la vérification de code peut empêcher l'utilisation illimitée
goto
, je suis tombé il y a longtemps sur une structure de contrôle utile pour les interfaces utilisateur à changement dynamique. Je l'ai appelé exécution différentielle . Il est entièrement universel Turing, mais sa preuve de correction dépend de la programmation structurée pur - pasgoto
,return
,continue
,break
ou exceptions.la source
Pourquoi est-ce que c'est dangereux?
goto
ne provoque pas l'instabilité par lui-même. Malgré environ 100 000goto
secondes, le noyau Linux reste un modèle de stabilité.goto
à lui seul ne devrait pas causer de failles de sécurité Cependant, dans certaines langues, le fait de le mélanger avec des blocs de gestiontry
/catch
exception pourrait conduire à des vulnérabilités, comme expliqué dans cette recommandation CERT . Les compilateurs C ++ traditionnels signalent et empêchent de telles erreurs, mais malheureusement, les compilateurs plus anciens ou plus exotiques ne le font pas.goto
provoque un code illisible et non maintenable. C'est ce qu'on appelle aussi le code spaghetti , parce que, comme dans une assiette à spaghetti, il est très difficile de suivre le flux de contrôle quand il y a trop de gotos.Même si vous réussissez à éviter le code spaghetti et si vous n'utilisez que quelques gotos, ils facilitent tout de même les problèmes de type bugs et fuites de ressources:
goto
déclaration, vous interrompez ce flux simple et les attentes. Par exemple, vous ne remarquerez peut-être pas qu'il vous reste encore des ressources à libérer.goto
dans des endroits différents peuvent vous envoyer à une cible unique. Il n'est donc pas évident de savoir avec certitude l'état dans lequel vous vous trouvez lorsque vous atteignez cet endroit. Le risque de faire des hypothèses erronées / non fondées est donc assez grand.Informations complémentaires et citations:
E.Dijkstra a écrit un premier essai sur le sujet en 1968: " Déclaration jugée nuisible "
Brian.W.Kernighan & Dennis.M.Ritchie a écrit dans le langage de programmation C:
James Gosling & Henry McGilton ont écrit dans leur livre blanc sur l’environnement de langage Java de 1995 :
Bjarne Stroustrup définit goto dans son glossaire en ces termes attrayants:
Quand peut-on utiliser?
Comme K & R, je ne suis pas dogmatique à propos de gotos. J'admets qu'il y a des situations où aller se détendre peut être facilité.
Généralement, en C, goto autorise la sortie de boucle multiniveau ou la gestion des erreurs nécessitant d'atteindre un point de sortie approprié qui libère / déverrouille toutes les ressources allouées jusqu'à présent (une allocation multiple en séquence signifie plusieurs libellés). Cet article quantifie les différentes utilisations du goto dans le noyau Linux.
Personnellement, je préfère l'éviter et en 10 ans de C, j'ai utilisé un maximum de 10 gotos. Je préfère utiliser des
if
s imbriqués , que je pense plus lisibles. Lorsque cela conduirait à une imbrication trop profonde, je choisirais soit de décomposer ma fonction en parties plus petites, soit d'utiliser un indicateur booléen en cascade. Les compilateurs d'optimisation actuels sont suffisamment intelligents pour générer presque le même code que le même codegoto
.L'utilisation de goto dépend fortement de la langue:
En C ++, l'utilisation correcte de RAII amène le compilateur à détruire automatiquement les objets qui sortent du domaine, de sorte que les ressources / le verrou soient nettoyés de toute façon, et qu'il n'y ait plus vraiment besoin de goto.
En Java , il n'y a pas besoin de goto (voir la citation de l' auteur de Java ci - dessus et cette excellente pile réponse Overflow ): le collecteur d'ordures qui nettoie le désordre,
break
,continue
ettry
/catch
couvrir la gestion des exceptions tous les cas oùgoto
pourrait être utile, mais dans un monde plus sûr et mieux manière. La popularité de Java prouve que la déclaration goto peut être évitée dans un langage moderne.Zoom sur la fameuse vulnérabilité SSL goto fail
Important Disclaimer: compte tenu de la discussion acharnée dans les commentaires, je tiens à préciser que je ne prétends pas que la déclaration goto est la seule cause de ce bogue. Je ne prétends pas que sans goto il n'y aurait pas de problème. Je veux juste montrer qu'un goto peut être impliqué dans un bug sérieux.
Je ne sais pas à combien de bugs sérieux sont liés
goto
dans l'histoire de la programmation: les détails ne sont souvent pas communiqués. Cependant, il y avait un fameux bogue Apple SSL qui affaiblissait la sécurité d'iOS. La déclaration qui a conduit à ce bogue était unegoto
déclaration fausse .Certains avancent que la cause principale du bogue n’était pas l’instruction goto en soi, mais un copier / coller incorrect, une indentation trompeuse, des accolades manquantes autour du bloc conditionnel ou peut-être les habitudes de travail du développeur. Je ne peux en confirmer aucun: tous ces arguments sont des hypothèses probables et une interprétation. Personne ne sait vraiment. ( entre temps, l'hypothèse d'une fusion qui a mal tourné, comme le suggère quelqu'un dans les commentaires, semble être un très bon candidat compte tenu d'autres incohérences d'indentation dans la même fonction ).
Le seul fait objectif est qu'un doublon a
goto
conduit à quitter la fonction prématurément. En regardant le code, la seule autre déclaration qui aurait pu causer le même effet aurait été un retour.L'erreur est en fonction
SSLEncodeSignedServerKeyExchange()
dans ce fichier :En effet, des accolades autour du bloc conditionnel auraient pu empêcher le bogue:
cela aurait entraîné soit une erreur de syntaxe lors de la compilation (et donc une correction), soit un goto redondant et inoffensif. À propos, GCC 6 serait en mesure de détecter ces erreurs grâce à son avertissement facultatif pour détecter une indentation incohérente.
Mais en premier lieu, tous ces gotos auraient pu être évités avec un code plus structuré. Donc, goto est au moins indirectement une cause de ce bogue. Il y a au moins deux manières différentes qui auraient pu l'éviter:
Approche 1: si clause ou
if
s imbriquéAu lieu de tester séquentiellement de nombreuses conditions d'erreur et d'envoyer chaque fois à une
fail
étiquette en cas de problème, on aurait pu opter pour l'exécution des opérations cryptographiques dans uneif
instruction qui ne le ferait que s'il n'y avait pas de précondition erronée:Approche 2: utiliser un accumulateur d'erreur
Cette approche est basée sur le fait que presque toutes les instructions ici appellent une fonction pour définir un
err
code d'erreur et n'exécutent le reste du code que sierr
0 (c'est-à-dire une fonction exécutée sans erreur). Une alternative sûre et lisible est:Ici, il n’ya pas un seul goto: aucun risque de sauter rapidement au point de sortie de la panne. Et visuellement, il serait facile de repérer une ligne mal alignée ou une ligne oubliée
ok &&
.Cette construction est plus compacte. Il est basé sur le fait que dans C, la deuxième partie d'un logique and (
&&
) n'est évaluée que si la première partie est vraie. En fait, l'assembleur généré par un compilateur optimiseur est presque équivalent au code original avec gotos: l'optimiseur détecte très bien la chaîne de conditions et génère du code qui, à la première valeur de retour non nulle, saute à la fin ( preuve en ligne ).Vous pourriez même envisager une vérification de cohérence à la fin de la fonction qui pourrait, au cours de la phase de test, identifier des incohérences entre l'indicateur ok et le code d'erreur.
Des erreurs telles qu'un
==0
remplacement par inadvertance par un!=0
connecteur logique ou des erreurs pourraient facilement être repérées pendant la phase de débogage.Comme dit: je ne prétends pas que des constructions alternatives auraient évité tout bug. Je veux juste dire qu'ils auraient pu rendre le virus plus difficile à produire.
la source
goto
accoladesif
. Mais si vous suggérez qu'évitergoto
rendra votre code à l'abri des effets des lignes dupliquées de manière aléatoire, j'ai de mauvaises nouvelles pour vous.if
instruction? Des moments de plaisir. :)Le célèbre article de Dijkstra a été écrit à une époque où certains langages de programmation étaient en réalité capables de créer des sous-programmes comportant plusieurs points d'entrée et de sortie. En d'autres termes, vous pouvez littéralement sauter au milieu d'une fonction et en sortir à n'importe quel endroit de la fonction, sans appeler cette fonction ou en revenir de manière conventionnelle. C'est toujours vrai du langage d'assemblage. Personne n'a jamais prétendu qu'une telle approche était supérieure à la méthode structurée d'écriture de logiciel que nous utilisons maintenant.
Dans la plupart des langages de programmation modernes, les fonctions sont très spécifiquement définies avec une entrée et un point de sortie. Le point d'entrée est l'endroit où vous spécifiez les paramètres de la fonction et l'appelez, et le point de sortie est l'endroit où vous renvoyez la valeur résultante et continuez l'exécution à l'instruction suivant l'appel de la fonction d'origine.
Dans le cadre de cette fonction, vous devriez pouvoir faire ce que vous voulez, dans des limites raisonnables. Si mettre un ou deux goto dans la fonction rend plus claire ou améliore votre vitesse, pourquoi pas? L’intérêt d’une fonction est de séquestrer un peu de fonctionnalités clairement définies, de sorte que vous n’ayez plus à penser à la manière dont elle fonctionne en interne. Une fois que c'est écrit, il vous suffit de l'utiliser.
Et oui, vous pouvez avoir plusieurs instructions return dans une fonction. il y a toujours toujours une place dans une fonction correcte à partir de laquelle vous revenez (le côté arrière de la fonction, en gros). Ce n'est pas du tout la même chose que de sauter d'une fonction avec un goto avant qu'il ait une chance de revenir correctement.
Donc, il ne s'agit pas vraiment d'utiliser des gotos. Il s'agit d'éviter leurs abus. Tout le monde convient que vous pouvez créer un programme extrêmement compliqué à l'aide de gotos, mais vous pouvez également en faire autant en abusant de fonctions (c'est beaucoup plus facile en abusant de gotos).
Pour ce que cela vaut, depuis que je suis passé des programmes BASIC de type ligne à numéro à la programmation structurée à l'aide de langages Pascal et accolades, je n'ai jamais eu à utiliser un goto. La seule fois où j'ai été tenté d’en utiliser une, c’est de sortir rapidement d’une boucle imbriquée (dans les langues qui ne prennent pas en charge la sortie précoce de boucles à plusieurs niveaux), mais je peux généralement trouver une autre méthode plus propre.
la source
J'avais l'habitude d'utiliser des
goto
instructions lorsque j'écrivais des programmes BASIC en tant qu'enfant comme moyen simple d'obtenir des boucles for et While (le Commodore 64 BASIC ne disposait pas de boucles en boucle et j'étais trop immature pour apprendre la syntaxe et l'utilisation appropriées de la boucle for ). Mon code était souvent trivial, mais tout problème de boucle pouvait être immédiatement attribué à mon utilisation de goto.J'utilise maintenant principalement Python, un langage de programmation de haut niveau qui a déterminé qu'il n'avait pas besoin de goto.
Lorsque Edsger Dijkstra a déclaré « Goto considéré comme nocif » en 1968 , il n'a pas donné une poignée d'exemples où les bugs liés pourraient être mis sur le compte goto, plutôt, il a déclaré que
goto
était inutile pour les langues de niveau supérieur et qu'il devrait être évité en faveur de ce nous considérons aujourd'hui le flux de contrôle normal: boucles et conditionnelles. Ses paroles:Il a probablement eu des tas de bogues à chaque fois qu’il déboguait du code
goto
. Mais son document était une déclaration de position généralisée, étayée par une preuvegoto
inutile pour les langages de niveau supérieur. Le bogue généralisé est qu’il est possible que vous ne puissiez pas analyser statiquement le code en question.Le code est beaucoup plus difficile à analyser statiquement avec des
goto
instructions, en particulier si vous revenez en arrière dans votre flux de contrôle (ce que je faisais auparavant) ou à une section de code non liée. Le code peut et a été écrit de cette façon. Cela a été fait pour optimiser fortement les ressources informatiques très rares et donc les architectures des machines.Un exemple apocryphe
Il y avait un programme de blackjack qu'un responsable a trouvé très optimisé mais impossible à "réparer" en raison de la nature du code. Elle a été programmée dans un code machine qui dépend fortement de la méthode gotos - je pense donc que cette histoire est tout à fait pertinente. C’est le meilleur exemple canonique auquel je puisse penser.
Un contre-exemple
Cependant, la source C de CPython (l’implémentation Python la plus courante et la plus utilisée) utilise des
goto
instructions très efficaces. Ils sont utilisés pour contourner les flux de contrôle non pertinents dans les fonctions pour arriver à la fin des fonctions, ce qui les rend plus efficaces sans perdre en lisibilité. Ceci respecte l'un des idéaux de la programmation structurée : avoir un seul point de sortie pour les fonctions.Pour mémoire, je trouve que ce contre-exemple est assez facile à analyser statiquement.
la source
Lorsque le wigwam était un art architectural actuel, leurs constructeurs pouvaient sans aucun doute vous donner de judicieux conseils pratiques concernant la construction de wigwams, la façon de laisser la fumée s'échapper, etc. Heureusement, les constructeurs d'aujourd'hui peuvent probablement oublier la plupart de ces conseils.
Lorsque la diligence était un art de transport actuel, leurs conducteurs pourraient sans aucun doute vous donner de judicieux conseils pratiques concernant les chevaux de diligence, la façon de se défendre contre les grands bandits de route, etc. Heureusement, les automobilistes d'aujourd'hui peuvent également oublier la plupart de ces conseils.
Lorsque les cartes perforées constituaient un art de programmation courant, leurs praticiens pourraient également vous donner de judicieux conseils pratiques concernant l’organisation des cartes, la numérotation des relevés, etc. Je ne suis pas sûr que ce conseil soit très pertinent aujourd'hui.
Êtes-vous déjà assez âgé pour connaître la phrase "numéroter des déclarations" ? Vous n'avez pas besoin de le savoir, mais si vous ne le savez pas, vous ne connaissez pas le contexte historique dans lequel la mise en garde
goto
était principalement pertinente.L'avertissement contre
goto
n'est tout simplement pas très pertinent aujourd'hui. Avec une formation de base sur les boucles while / for et les appels de fonction, vous ne penserez même pas à en donnergoto
très souvent. Quand vous y réfléchissez, vous avez probablement une raison, alors allez-y.Mais ne pouvez-vous
goto
pas abuser de cette déclaration?Réponse: bien sûr, il peut être utilisé de manière abusive, mais son utilisation est un problème minuscule en génie logiciel par rapport à des erreurs bien plus courantes, telles que l’utilisation d’une variable où une constante servira ou d’une programmation par copier-coller (sinon connu sous le nom négligence de refactor). Je doute que vous soyez beaucoup en danger. Sauf si vous utilisez
longjmp
ou transférez de toute autre manière le contrôle vers du code éloigné, si vous pensez utiliser ungoto
ou vous souhaitez simplement l'essayer pour le plaisir, continuez. Ça ira.Vous remarquerez peut-être le manque d' histoires d'horreur récentes dans lesquelles
goto
joue le méchant. La plupart ou la totalité de ces histoires semblent avoir 30 ou 40 ans. Vous vous tenez sur des bases solides si vous considérez que ces histoires sont pour la plupart obsolètes.la source
Pour ajouter une chose aux autres excellentes réponses, avec des
goto
déclarations, il peut être difficile de dire exactement comment vous êtes arrivé à un endroit donné du programme. Vous pouvez savoir qu'une exception s'est produite sur une ligne spécifique, mais s'il y agoto
des éléments dans le code, il n'y a aucun moyen de déterminer les instructions exécutées pour que cette exception provoque un état sans rechercher l'ensemble du programme. Il n'y a pas de pile d'appels ni de flux visuel. Il est possible qu'il existe une instruction distante de 1000 lignes qui vous a mis dans un mauvais état et qui a exécutégoto
une exception sur la ligne qui a généré une exception.la source
On Error Goto errh
, vous pouvez utiliserResume
pour réessayer,Resume Next
pour ignorer la ligne incriminée etErl
pour savoir de quelle ligne il s'agissait (si vous utilisez des numéros de ligne).Resume
va ré-exécuter cette fonction depuis le début etResume Next
ignorer tout ce qui ne l’a pas encore été.On Error Goto 0
et manuellement Debug.Resume
est destiné à être utilisé après vérificationErr.Number
et ajustements nécessaires.goto
ne fonctionne qu'avec des lignes étiquetées, qui semblent avoir été remplacées par des boucles étiquetées .Les humains ont plus de mal à raisonner que les autres formes de contrôle de flux.
Programmer le bon code est difficile. Écrire des programmes corrects est difficile, déterminer si les programmes sont corrects est difficile, prouver qu'il est correct de le faire.
Obtenir du code pour faire vaguement ce que vous voulez est facile comparé à tout ce qui concerne la programmation.
goto résout certains programmes en obtenant du code pour faire ce que vous voulez. Cela ne facilite pas la vérification de l'exactitude, contrairement à ses alternatives.
Il existe des styles de programmation pour lesquels goto est la solution appropriée. Il y a même des styles de programmation où son jumeau diabolique, le comefrom, est la solution appropriée. Dans les deux cas, vous devez faire très attention à ce que vous l'utilisiez de manière compréhensible, et à de nombreuses vérifications manuelles pour vérifier que vous ne faites pas quelque chose de difficile pour en assurer l'exactitude.
À titre d’exemple, il existe une fonctionnalité de certaines langues appelée coroutines. Les coroutines sont des threads sans fil; état d'exécution sans thread pour l'exécuter. Vous pouvez leur demander de s’exécuter, et ils peuvent exécuter une partie d’eux-mêmes, puis se suspendre, ce qui leur rend le contrôle du flux.
Des routines "peu profondes" dans des langages sans prise en charge de coroutines (comme C ++ pré-C ++ 20 et C) sont possibles en utilisant un mélange de gotos et de gestion manuelle des états. Les coroutines "profondes" peuvent être réalisées à l'aide des fonctions
setjmp
etlongjmp
de C.Il y a des cas où les coroutines sont si utiles que les écrire manuellement et avec soin en vaut la peine.
Dans le cas de C ++, ils sont jugés suffisamment utiles pour étendre le langage pour les prendre en charge. La
goto
gestion des états et manuelle est cachée derrière une couche d’abstraction sans coût, ce qui permet aux programmeurs de les écrire sans la difficulté de prouver leur fouillis d’objectifs, devoid**
construction manuelle / destruction d’état, etc.Le goto se cache derrière une abstraction de niveau supérieur, comme
while
oufor
ouif
ouswitch
. Ces abstractions de niveau supérieur sont plus faciles à prouver et à vérifier.Si la langue en manquait certaines (comme certaines langues modernes, il manque des coroutines), vous pouvez utiliser l'un des motifs suivants: un motif qui ne correspond pas au problème ou utiliser la méthode goto.
Obtenir un ordinateur pour faire vaguement ce que vous voulez qu'il fasse dans les cas courants est facile . Écrire du code fiable et robuste est difficile . Goto aide le premier beaucoup plus que le second; d'où "goto considéré comme nuisible", car il s'agit d'un code de "travail" superficiel avec des bogues profonds et difficiles à détecter. Avec suffisamment d’effort, vous pouvez toujours créer du code avec "goto" de manière fiable, ce qui rend mal la règle absolue. mais en règle générale, c’est un bon choix.
la source
longjmp
est seulement légal en C pour dérouler la pilesetjmp
dans une fonction parent. (C'est comme sortir de plusieurs niveaux d'imbrication, mais pour les appels de fonction au lieu de boucles).longjjmp
dans un contexte desetjmp
fait dans une fonction qui est revenue depuis n'est pas légal (et je suppose que cela ne fonctionnera pas dans la pratique dans la plupart des cas). Je ne suis pas au courant de co-routines, mais de votre description d'une co-routine semblable à un fil de l' espace utilisateur, je pense qu'il aurait besoin de sa propre pile, ainsi qu'un contexte registre enregistré, etlongjmp
ne vous donne inscrivez -saving, pas une pile séparée.Jetez un coup d’œil à ce code, disponible à l’ adresse http://www-personal.umich.edu/~axe/research/Software/CC/CC2/TourExec1.1.f.html, qui faisait en fait partie d’une grande simulation du dilemme d’un prisonnier. Si vous avez vu l'ancien code FORTRAN ou BASIC, vous comprendrez que ce n'est pas si inhabituel.
Beaucoup de problèmes ici vont bien au-delà de la déclaration de GOTO; Honnêtement, je pense que la déclaration de GOTO était un peu un bouc émissaire. Mais le flux de contrôle n'est absolument pas clair ici, et le code est mélangé de manière à rendre très flou ce qui se passe. Même sans ajouter de commentaires ou utiliser de meilleurs noms de variables, changer cela en une structure de bloc sans GOTO faciliterait grandement la lecture et le suivi.
la source
L' encapsulation est l'un des principes de la programmation maintenable . Le fait est que vous vous connectez à un module / une routine / un sous-programme / un composant / un objet en utilisant une interface définie, et uniquement cette interface, et les résultats seront prévisibles (en supposant que l'unité a été testée de manière efficace).
Dans une même unité de code, le même principe s'applique. Si vous appliquez systématiquement les principes de la programmation structurée ou orientée objet, vous ne pourrez pas:
Parmi les symptômes les plus courants de ces erreurs de traitement figurent les fuites de mémoire, l'accumulation de mémoire, les débordements de pointeur, les blocages, les enregistrements de données incomplets, les exceptions d'ajout / enregistrement / suppression d'enregistrements, les erreurs de page de mémoire, etc.
Les manifestations de ces problèmes observables par l'utilisateur incluent le verrouillage de l'interface utilisateur, la diminution progressive des performances, des enregistrements de données incomplets, l'impossibilité d'initier ou de terminer des transactions, des données corrompues, des pannes de réseau, des pannes de courant, des pannes de systèmes embarqués (du fait de la perte de contrôle des missiles perte de capacité de suivi et de contrôle dans les systèmes de contrôle de la circulation aérienne), défaillances de minuterie, etc., etc. Le catalogue est très complet.
la source
goto
même une fois. :)goto est dangereux car il est généralement utilisé là où il n’est pas nécessaire. Utiliser tout ce qui n'est pas nécessaire est dangereux, mais surtout , allez-y . Si vous google, vous rencontrerez beaucoup d'erreurs causées par goto, ce n'est pas une raison en soi de ne pas l'utiliser (des bugs surviennent toujours lorsque vous utilisez des fonctionnalités du langage car c'est intrinsèque à la programmation), mais certaines d'entre elles sont clairement très liées à goto utilisation.
Raisons d'utiliser / ne pas utiliser goto :
Si vous avez besoin d'une boucle, vous devez utiliser
while
oufor
.Si vous devez faire un saut conditionnel, utilisez
if/then/else
Si vous avez besoin d'une procédure, appelez une fonction / méthode.
Si vous avez besoin de quitter une fonction, juste
return
.Je peux compter sur mes doigts les endroits où j'ai vu
goto
utilisé et utilisé correctement.Dans libKTX il y a une fonction qui a le code suivant
Maintenant, dans cet endroit
goto
est utile parce que le langage est C:Ce cas d’utilisation est utile car en C, nous n’avons pas de classes, le moyen le plus simple de nettoyer consiste donc à utiliser un fichier
goto
.Si nous avions le même code en C ++, plus besoin de goto:
À quel genre de bugs cela peut-il conduire? N'importe quoi. Boucles infinies, mauvais ordre d’exécution, vis de pile ..
Un cas documenté est une vulnérabilité de SSL autorisant des attaques de type Man in the Middle causées par une mauvaise utilisation de goto: voici l'article
C'est une erreur de frappe, mais est passé inaperçu pendant un moment, si le code était structuré d'une autre manière, correctement testé, une telle erreur n'aurait peut-être pas été possible.
la source