[BUG] GOTO/END : erreurs + RALENTISSEMENT |
Auteur |
Message |
linkakro
Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
|
Posté le : Lun 11 Juil 2011, 17:59
|
|
|
(edit global 15/3/2013)
(edit mineur 31/12/2013)
La mauvaise utilisation des Goto ou des Menu dans des boucles/alternatives peut provoquer des bugs ou un ralentissement.
D'une manière générale, la moindre manipulation perturbant des End peut poser problème.
Mais le grand classique demeure l'excès de Goto.
Toutefois les bugs peuvent être exploités volontairement à condition de savoir ce qu'on fait !
Par exemple, le tuto suivant du sdz explique comment se servir volontairement de certains bugs.
http://www.siteduzero.com/tutoriel-3-407869-amusons-nous-avec-les-end.html
edit --- ce n'est plus site du zero mais OpenClassrooms
Mon objectif ici est d'exposer les Bugs et d'expliquer le phénomène
D'ailleurs ce phénomène devrait se produire dans tous les languages interprétés (=sans compilation) possédant le Goto sans le surveiller.
EDIT : 23/5/2013 : autre sujet dans un cas typique, et explication par quelqu'un d'autre que moi. http://tout82.free.fr/forum/sujet.php?sujet=3788
===== Principe
La calculatrice semble garder en mémoire chaque boucle/alternative ouverte dans un programme jusqu'à l'arrêt du programme.
Quand la calculatrice rencontre un End, elle ferme la dernière boucle/alternative ouverte.
(lors de l'arrêt elle ferme tout)
Or les Goto empêchent la calculatrice de lire toutes les instructions du code.
Donc il arrive que des boucles ne soient pas fermées.
Ou encore qu'on en ouvre une plusieurs fois.
De plus End est la seule instruction qui permette de fermer les boucles/alternatives, donc il peut y avoir des confusions.
===== Remarque
Une alternative utilise un Then.
Un If seul ne se comporte pas comme une alternative.
En effet le If ne stocke pas d'information dans la pile.
Il faut le combiner à Then et [ End ou Else ] pour obtenir une alternative.
Cela permet de modifier le comportement sans avoir besoin de End plus tard.
===== Conséquence 1 : ralenti
Si on ne ferme pas les boucles/alternatives, la calculatrice ralentit jusqu'à saturation mémoire.
C'est le problème classique des jeux snake ratés.
Code | Lbl A
If B
Then // cette alternative ne sera pas fermée après execution
Goto A
End // non lu si B est vrai |
Bonus : Remarquez que le End de cet exemple est facultatif s'il est à la fin. Sinon TOUTE la fin du programme est ignorée pour B faux.
===== Conséquence 2 : confusion
Quand le Goto envoie hors d'une boucle/alternative :
Le prochain End rencontré (quel qu'il soit) sera interprété comme fin de la précédente boucle/alternative quittée même s'il n'a aucun rapport.
Si le Goto envoie hors d'un Then (alternative) :
SOIT : Le prochain End est sans effet
SOIT : Le prochain Else provoquera un saut jusqu'au prochain End (quel qu'il soit)
Code | If 1
Then
Goto A
End // sans importance
// ailleurs dans le programme ... voir même avant !!! //
For // boucle quelconque
Lbl A
... // rien ou des boucles refermées
End // ne fait rien (comme une fin de If), alors qu'il devrait renvoyer au For
|
Code | For(W,1,2
If 1
Then
Goto 1
End
Lbl 1
... // rien ou des boucles refermées
End // ce End ferme le If , alors qu'il devrait renvoyer au For
|
Si le Goto envoie hors d'une boucle :
SOIT : le prochain End provoquera un retour au début de la boucle
SOIT : il ne se passe rien
Consulter la section "usage volontaire" qui utilise cela.
===== Usage volontaire (routines et boucles)
(voir tuto sdz indiqué en lien et conséquence 2 (confusion))
Code | Goto 0
Lbl 1
End //ramène au while 1
Lbl 0
While 1
Goto 1 |
Remarque (edit 3/3/12) : On peut perturber des boucles sans Goto comme dans cet exemple suivant.
Code | While 1
If A
End //ramène au début si la condition A est vraie
If B
End // idem, condition B |
Ne pas exploiter ce bug n'importe quand... surtout pas dans une autre boucle si on ne referme pas.
Code | If
Then
For(
...
If
End // Ce End est soumis au If, comme précédemment
End // TANTOT MARCHE, TANTOT CONFONDU AVEC LE PRECEDENT |
Tiré du tutoriel d'OpenClassrooms >>> ROUTINE FACILE
Code | ...
For(A,1,2 // execution routine
If A-2
Goto 0
End
...// fin programme
Stop
Lbl 0
... // routine
End // retour |
Remarque ajoutée 31/12/2013 :
Si vous voulez créer des routines de cette manière et que cela soit rapide, vous avez intérêt à placer le Label le plus tôt possible dans le programme, ou bien que cela soit à l'intérieur d'un programme court.
CONTOURNER DES BUGS : (n'hésitez pas à me proposer de nouveaux exemples)
(edit 24/6/12)
Pour pouvoir quitter une boucle sans provoquer de bug, il suffit parfois d'appeler un programme dans un autre et de quitter avec la commande Return.
En effet l'arrêt d'un programme (même appelé) libère la mémoire vive de ses boucles.
Code |
Code | // programme BOUCLE
While 1
Return // quitte le programme donc la boucle, sans bug
End
Return // sous-entendu car à la fin |
|
--- (edit 15/02/12)
Répartir différemment les instructions pour extraire le(s) Goto(s)
Code | If A
Then
...
Goto 0 // supprimmer
Else
...
Goto 0 // supprimmer
End
Goto 0 // ajouter
|
Utiliser le fait qu'un If seul ne se comporte pas comme un alternative pour extraire le Goto.
Code |
Code | If A
Then
... // algo ne modifiant pas les données du test A
Goto 0
End |
devient
Code | If A
Then
... // algo ne modifiant pas les données du test A
End
If A // même test que juste au dessus
Goto 0 |
Fonctionne aussi avec un Else dans la structure tant que les instructions contenues n'influencent pas le test. |
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Pour tout le monde et surtout les débutants, quelques-uns des articles courants :
*Traductions Algorithmie/Ti-Basic.
*Caractères spéciaux sur Tout82
Les défauts du TI-Basic : Goto_versus_algo et DelVar/End/Lbl/guillemet/store |
 |
|
|
Sangohan38
Autorisation : Membre
Nb de messages : 3370
Inscrit le : Sam 31 Déc 2005, 19:48
|
Posté le : Lun 11 Juil 2011, 18:04
|
|
|
Normal que la boucle for ne soit pas comprise lors du saut puisque la calcu ne fait que lire dans l'ordre où ça arrive donc elle ne peut pas savoir que la boucle existe
De la même façon, je pense que si tu met un programme du genre
Code | for(A,1,10
lbl 1
end
for(B,1,50
goto 1
disp A
end |
A mon avis, B ne changera pas puisque le second for n'est jamais atteint et donc la boucle s'arrêtera à 10.
Sangohan38
|
 |
|
|
linkakro
Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
|
Posté le : Lun 11 Juil 2011, 18:18
|
|
|
Ton observation des For est correcte.
Cependant la cause du bug n'est pas toujours la définition de la boucle.
La calculatrice garde en mémoire chaque boucle ouverte.
Quand elle lit un End, elle ferme la dernière boucle qu'elle se souvient avoir ouverte.
Si la dernière boucle ouverte est Then, alors le End ferme le Then au lieu de sa boucle.
Code | For(W,1,2
If 1
Then
Goto 1
End
Lbl 1
End // ce End n'est pas reconnu |
PS: c'est le bug que j'ai combattu dans mon STOECHIO
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Pour tout le monde et surtout les débutants, quelques-uns des articles courants :
*Traductions Algorithmie/Ti-Basic.
*Caractères spéciaux sur Tout82
Les défauts du TI-Basic : Goto_versus_algo et DelVar/End/Lbl/guillemet/store |
 |
|
|
Sangohan38
Autorisation : Membre
Nb de messages : 3370
Inscrit le : Sam 31 Déc 2005, 19:48
|
Posté le : Lun 11 Juil 2011, 19:08
|
|
|
Ce n'est donc pas un bug mais simplement de la logique dans ce cas car d'une part la calculatrice ne ferme rien sans qu'on lui ordonne et d'autre part, le goto n'est pas la cause d'un bug mais juste un moyen d'augmenter la taille de la boucle.
Bref le titre est mal choisis selon moi par contre l'idée de fond est intéressante mais mériterait d'être plus développée.
Sangohan38
|
 |
|
|
linkakro
Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
|
Posté le : Lun 11 Juil 2011, 19:20
|
|
|
Tu as raison en disant qu'appeler cela "le bug des Goto" est mal choisi.
C'est la mauvaise utilisation de la calculatrice qui provoque des bugs.
Je modifie le titre et ajoute le dernier exemple dans mon prmier message.
=====
EDIT : 18/9/11
en attendant de savoir où le mettre, je stocke ça ici :
Boucles :
Avantage : La TI retrouve immédiatement une entrée de boucle sans avoir à la chercher (contrairement aux Lbl)
Avantage : certaines structures logiques complexes ne peuvent être assurées efficacement que par une boucle While.
Inconvénient : La TI stocke en mémoire toutes les boucles jusqu'à ce quelles soient fermées.
Inconvénient : Une entrée de boucle ne peut servir que pour une seule boucle.
Goto :
Avantage : Un seul Lbl peut être lié à plusieurs Goto. (innutile dans notre programme)
Avantage : La TI ne garde pas en mémoire les Goto et Lbl.
Incovénient : La TI cherche un Lbl en parcourant tout le programme. Cela se ressent dans les gros programmes.
Dernier critère :
Parfois seule la mémoire occupée dans le code permet de choisir.
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Pour tout le monde et surtout les débutants, quelques-uns des articles courants :
*Traductions Algorithmie/Ti-Basic.
*Caractères spéciaux sur Tout82
Les défauts du TI-Basic : Goto_versus_algo et DelVar/End/Lbl/guillemet/store |
 |
|
|
F-BVXT
Autorisation : Membre
Nb de messages : 178
Inscrit le : Dim 27 Mai 2012, 20:38
|
Posté le : Sam 09 Jui 2012, 12:15
|
|
|
Super cet article, mais du coup ça veut dire qu'on peut fermer une boucle avant qu'elle ne soit ouverte, comme ça par exemple :
Code | If ...
Then
... //Instruction quelconque
... //Instruction quelconque
LBL 1
End
If ...
Then
... //Instruction quelconque
... //Instruction quelconque
Goto 1 |
C'est bien ça ?
Sinon pour les corrections de bugs je propose :
Code | If ...
Then
...
Goto 0
...
LBL 0
End |
---------------------- Il y a 10 types de personnes dans le monde : celles qui comprennent le binaire et celles qui ne le comprennent pas. |
 |
|
|
linkakro
Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
|
Posté le : Sam 09 Jui 2012, 14:56
|
|
|
Pas exactement.
Lorsque la TI lit le goto, elle doit avoir en mémoire l'ouverture du If précédent, et seulement lui, car l'autre boucle avait déjà été refermée.
Lorsqu'elle atteind le Lbl 1 en sortant du goto, elle lit un End qu'elle interprête comme la fin du dernier If ouvert, c'est-à-dire le deuxième !
Code | If ...
Then // ouvert 1 fois
Lbl 1
End // ferme le premier then la première fois // ferme ensuite le deuxième
If ...
Then // ouvert
Goto 1 |
Dans cet exemple complémentaire, on voit que le End n'est pas reconnu car aucune boucle n'est en mémoire.
Code | If ...
Then // ouvert 1 fois
Lbl 1
End // provoque une erreur la deuxième fois !
Goto 1 |
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Pour tout le monde et surtout les débutants, quelques-uns des articles courants :
*Traductions Algorithmie/Ti-Basic.
*Caractères spéciaux sur Tout82
Les défauts du TI-Basic : Goto_versus_algo et DelVar/End/Lbl/guillemet/store |
 |
|
|
F-BVXT
Autorisation : Membre
Nb de messages : 178
Inscrit le : Dim 27 Mai 2012, 20:38
|
Posté le : Sam 09 Jui 2012, 15:36
|
|
|
Citer | Lorsque la TI lit le goto, elle doit avoir en mémoire l'ouverture du If précédent, et seulement lui, car l'autre boucle avait déjà été refermée.
Lorsqu'elle atteind le Lbl 1 en sortant du goto, elle lit un End qu'elle interprête comme la fin du dernier If ouvert, c'est-à-dire le deuxième ! |
Oui c'est que j'avais compris mais je me suis mal exprimé, ce que je voulais dire c'est qu'on pouvait placer un End de fin de boucle avant le début de cette boucle. Ce qui est donc le cas.
---------------------- Il y a 10 types de personnes dans le monde : celles qui comprennent le binaire et celles qui ne le comprennent pas. |
 |
|
|
linkakro
Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
|
Posté le : Sam 09 Jui 2012, 20:48
|
|
|
On peut mettre un End n'importe-où pourvu qu'une boucle ait été ouverte précédemment, et qu'on soit sûr du fonctionnement.
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Pour tout le monde et surtout les débutants, quelques-uns des articles courants :
*Traductions Algorithmie/Ti-Basic.
*Caractères spéciaux sur Tout82
Les défauts du TI-Basic : Goto_versus_algo et DelVar/End/Lbl/guillemet/store |
 |
|
|
thedarkprogrammeur
Autorisation : Membre
Nb de messages : 27
Inscrit le : Sam 09 Jui 2012, 21:58
|
Posté le : Sam 16 Jui 2012, 1:15
|
|
|
merci linkakro tu m'a permis de mieux comprendre le fonctionnement des ces Ends 
---------------------- Le jour que je deteste le plus?... le dimanche, car 32 heures après j'ai cours de sport |
 |
|
|
F-BVXT
Autorisation : Membre
Nb de messages : 178
Inscrit le : Dim 27 Mai 2012, 20:38
|
Posté le : Sam 16 Jui 2012, 23:19
|
|
|
Comme je me suis fais avoir dans un précédent sujet et pourtant j'étais sûr de moi, je pense qu'il serait utile de donner un exemple avec une boucle (while ou repeat peu importe) et d'insister sur le fait qu'un End bien qu'éloigné, ramènera au début de cette boucle.
En effet :
Code | If A
Then
...
Goto 1
...
LBL 1
End |
Est une solution de correction dans le cas d'un If mais ne marche pas pour les boucles.
---------------------- Il y a 10 types de personnes dans le monde : celles qui comprennent le binaire et celles qui ne le comprennent pas. |
 |
|
|
linkakro
Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
|
Posté le : Sam 16 Jui 2012, 23:40
|
|
|
Tu viens de me rappeler que mon article ne contient pas le cas le plus exemplaire : le retour au début dans des boucles !
J'édite mon message principal.
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Pour tout le monde et surtout les débutants, quelques-uns des articles courants :
*Traductions Algorithmie/Ti-Basic.
*Caractères spéciaux sur Tout82
Les défauts du TI-Basic : Goto_versus_algo et DelVar/End/Lbl/guillemet/store |
 |
|
|
Google_AdSense
|
Publicité
|
|
|
|
|