Poster un nouveau sujet Poster une réponse
[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   Citer 

(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
prgmBOUCLE


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
 Adresse email Haut de page Bas de page 
 
Sangohan38



Autorisation : Membre
Nb de messages : 3370
Inscrit le : Sam 31 Déc 2005, 19:48
Posté le : Lun 11 Juil 2011, 18:04   Citer 

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

 Adresse email Haut de page Bas de page 
 
linkakro



Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Lun 11 Juil 2011, 18:18   Citer 

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
 Adresse email Haut de page Bas de page 
 
Google_AdSense



Publicité    



 
Sangohan38



Autorisation : Membre
Nb de messages : 3370
Inscrit le : Sam 31 Déc 2005, 19:48
Posté le : Lun 11 Juil 2011, 19:08   Citer 

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

 Adresse email Haut de page Bas de page 
 
linkakro



Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Lun 11 Juil 2011, 19:20   Citer 

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
 Adresse email Haut de page Bas de page 
 
F-BVXT



Autorisation : Membre
Nb de messages : 178
Inscrit le : Dim 27 Mai 2012, 20:38
Posté le : Sam 09 Jui 2012, 12:15   Citer 

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.
 Adresse email Haut de page Bas de page 
 
linkakro



Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Sam 09 Jui 2012, 14:56   Citer 

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
 Adresse email Haut de page Bas de page 
 
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 


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.
 Adresse email Haut de page Bas de page 
 
linkakro



Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Sam 09 Jui 2012, 20:48   Citer 

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
 Adresse email Haut de page Bas de page 
 
thedarkprogrammeur



Autorisation : Membre
Nb de messages : 27
Inscrit le : Sam 09 Jui 2012, 21:58
Posté le : Sam 16 Jui 2012, 1:15   Citer 

merci linkakro tu m'a permis de mieux comprendre le fonctionnement des ces Ends bigmouth.gif

----------------------
Le jour que je deteste le plus?... le dimanche, car 32 heures après j'ai cours de sport
 Adresse email Haut de page Bas de page 
 
F-BVXT



Autorisation : Membre
Nb de messages : 178
Inscrit le : Dim 27 Mai 2012, 20:38
Posté le : Sam 16 Jui 2012, 23:19   Citer 

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.
 Adresse email Haut de page Bas de page 
 
linkakro



Autorisation : Membre
Nb de messages : 3767
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Sam 16 Jui 2012, 23:40   Citer 

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
 Adresse email Haut de page Bas de page 
 
Poster un nouveau sujet Poster une réponse





  Powered by Fire-Soft-Board v1.0.10 © 2004 - 2024 Groupe FSB
Page générée en 9 requêtes
BlackOne par Grimmlink