Pb Stack overflow [PIC/C] - C - Programmation
Marsh Posté le 23-01-2011 à 13:43:40
A+,
Marsh Posté le 23-01-2011 à 18:41:40
heu... le code fait 700 lignes, et en plus c'est pas un problème lié à une ligne ou un bloc de lignes, mais a l'ensemble du programme (n'importe quelle ligne ajoutée/commentée peut donner un stack overflow/le supprimer)
ma question aurait plutôt du être :
Avez vous déja eu affaire à un stack overflow, et si oui comment l'avez vous résolu?
Marsh Posté le 23-01-2011 à 22:15:02
1. Vérifiez votre code, parce que généralement ce problème est causé par un bug (fuite mémoire ou appel récursif).
2. Vérifier votre code, parce que vous avez peut-être des variables locales, ou en paramètres, qui sont trop grandes.
3. Voyez si vous ne pourriez pas réduire vos besoins d'espace sur la pile.
4. Voyez si vous ne pourriez pas agrandir la pile.
Marsh Posté le 24-01-2011 à 19:36:04
merci de ta réponse billgatesanonym
voici quelques lignes de codes (j'ai testé et compilé, et en simulation sur isis, ça me lance des tonnes de "stack overflow" )
Code :
|
L'erreur, enfin les erreurs proviennent des lignes commentées (aux environs de la ligne 210)
Deux solutions pour faire réapparaitre les stack overflow :
-Dé-commenter une des lignes : fHauteurMur = fHauteurMur+0.1; (ou -0.1)
-Dé-commenter une des lignes : FloatToStr(fHauteurMur, cHauteurMur);
J'ai cherché l'erreur, et franchement je ne vois pas...
l'itération de fHauteurMur est des plus classiques, et la fonction FloatToStr est utilisée juste au dessus et ne pose aucun problème...
que je soit sûr : la pile c'est les boucles du genre while(), et un stack overflow correspond à trop de boucles imbriquées les unes dans les autres?
Dans ce cas, réduire mes besoins de pile, c'est changer un peu le programme pour utiliser moins de boucles?
Agrandir la pile? ça serait super ça, mais je ne sais pas si c'est possible avec un PIC...
petite question à part : Je n'arrive pas à écrire sur l'eeprom du pic en simulation, isis me donne ce code d'erreur :
Attempt to write to data EEPROM address 0x0010 not allowed - WRTD bit in configuration is not set
C'est sûrement très simple, mais je n'ai jamais encore jamais fait ça, et j'hésite entre : c'est le simulateur qui me l'empêche / il faut désactiver la protection au flashage du pic / Il faut rajouter un qqch au programme / c'est dans la configuration du compilateur... ça fait pas mal de chose et je ne sais pas trop où chercher ^^
Merci
Marsh Posté le 24-01-2011 à 22:43:43
Lorsque tu as le stack overflow, tu as decommente aussi les lignes "while(pHaut){}" et "while(pBas){}" ?
Ce qui est possible c'est que ton float fHauteur depasse les 4 characteres (+ 1 pour le charactere final) alloues initialement (ligne 37).
Si tu ne verifies pas que pHaut et pBas sont egales a zero, alors tes conditions seront tout le temps vraies et tu va facilement arriver a 100.0 ou -10.0 qui depassent les limites de ta chaine de caractere.
Marsh Posté le 25-01-2011 à 10:17:27
Les goto mettent sûrement la pagaille, par exemple les goto MainMenu_Params;
D'une manière générale, il est fortement déconseillé d'utiliser des goto, parce que cela rend le code difficilement lisible.
Mais il y a une autre raison, qui est que les compilateurs ont beaucoup de mal à les gérer dans certaines situations.
C'est pour cela qu'a été inventé l'instruction longjmp qui est comme un goto, mais sans certains problèmes.
Voir http://www.fmc-modeling.org/catego [...] ngjmp.html où il est écrit :
Citation : the Longjump concept is very similar to using "goto". However as opposed to longjmp(), "goto" will not restore any of the program's state. Therefore longjmp() can be used for jumps without corrupting the call stack. |
Edit : J'ai retrouvé une page sur les spécifications officielles du langage C http://c0x.coding-guidelines.com/6.8.6.1.html :
Citation : A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier. |
Voici d'autres pages sur le goto http://msdn.microsoft.com/en-us/li [...] s.80).aspx
Citation : It is good programming style to use the break, continue, and return statement in preference to goto whenever possible. |
Voir aussi http://www.codeguru.com/forum/show [...] light=goto
Marsh Posté le 25-01-2011 à 11:22:16
Le goto, c'est pas interdit en C, et il y a des situations (changements d'état d'un automate à états finis par exemple) ou c'est fortement utile et ou un setjmp/longjmp n'est pas optimal.
C'est déconseillé aux développeurs inexpérimentés.
Bon néanmoins dans la cas de ce code, on peut s'en passer au prix d'une variable exitcode supplémentaire.
Mais le pb ne vient pas probablement de cela.
Citation : Ce qui est possible c'est que ton float fHauteur depasse les 4 characteres (+ 1 pour le charactere final) alloues initialement (ligne 37). |
Ça me semble bien vu, et être probablement la cause du pb.
A+,
Marsh Posté le 25-01-2011 à 11:31:24
gilou a écrit : Le goto, c'est pas interdit en C |
Je n'ai jamais dit cela. Lisez avant de critiquer !
gilou a écrit : Mais le pb ne vient pas probablement de cela. |
Pourquoi vous dîtes cela ? Si vous critiquez, apportez des arguments. Ne le faîtes pas lâchement et arbitrairement.
Moi, je vous donne quatre références séireuses, qui donnent des exemples précis et similaires au cas présent, où le goto est la source de corruption de la pile. Et, vous, vous balayez ces quatre références d'un revers de main, sans aucun argument. Ce n'est pas comme cela que l'on discute sur un forum.
Marsh Posté le 25-01-2011 à 12:53:17
billgatesanonym a écrit : Je n'ai jamais dit cela. Lisez avant de critiquer ! |
Et ou ais-je dit que vous l'aviez dit? C'est quoi ce procès d'intention?
billgatesanonym a écrit : Si vous critiquez, apportez des arguments. |
La lecture du code est claire:
Parce que l'on voit bien ici les blocs étiquetés:
Code :
|
et
Code :
|
Et on a pas de problème de scope de variable associable aux gotos: Tout est soit des variables globales, soit des locales avec main pour scope ici.
A+,
Marsh Posté le 25-01-2011 à 13:28:50
merci de toutes vos réponses, ça fait vraiment plaisir
je regarde tout ça avec précision ce soir !
Marsh Posté le 25-01-2011 à 21:14:22
bon j'ai fait quelques tests, et j'ai eu une surprise...
Lignes 211, 213, 214 dé-commentée, ce qui donne ça :
Code :
|
et ça plante pas... (pourtant hier ça plantait bien)
par contre, si je dé-commente la ligne FloatToStr(...); , là ça plante directement !
j'ai essayé en déclarant fHauteurMur ainsi : float fHauteurMur[10]; et j'ai aussi essayé comme ça : float fHauteurMur[];
Dans les deux cas ==> stack overflow
ensuite j'ai aussi commenté tous les goto ... et leurs repères
==> Stack overflow, encore
Olivier51 :
Citation : Si tu ne verifies pas que pHaut et pBas sont egales a zero, alors tes conditions seront tout le temps vraies et tu va facilement arriver a 100.0 ou -10.0 qui depassent les limites de ta chaine de caractere. |
pHaut, pBas, ainsi que pDroite et pGauche sont des pins du PIC qui correspondent à un bouton poussoir
le truc c'est que un appui sur le bouton haut (en étant dans le menu Hauteur du mur bien sûr) augmente fHauteurMur de 10cm (normalement, le mur ne devrais pas dépasser les 13m ^^)
A moins d'avoir l'esprit torturé, fHauteurMur variera entre 5.0 et 15.0 (mais c'est vrai qu'il serait mieux d'y mettre des limites)
billgatesanonym :
Vu que j'ai supprimé tous les goto du programme et qu'il fait encore du stack overflow, je ne vais garder ce longjmp de côté, je suis sûr qu'il va me servir un moment ou un autre ^^
D'ailleurs, je pense même remplacer mes goto par des longjmp une fois que je n'aurais pas ce foutu stack overflow sur le dos !
gilou :
Citation : C'est déconseillé aux développeurs inexpérimentés |
ah bah merci !
... mais nan je plaisante
Dans mon 1er jet de programme, j'avait plein de while imbriqués, avec plein de trucs du genre "while(1){... nReturnBoucle=1;break; ...}switch(nReturnBoucle){case...}" ... enfin bref c'était carément chiant et presque bordélique. Ensuite je me suis dit : "Un goto, c'est pas beau, mais ça serait hyper plus simple pour passer d'un menu à l'autre !", et voila ce que ça a donné ^^
ps : pas besoin de se mettre sur la tronche pour ça
Marsh Posté le 25-01-2011 à 22:08:04
crom29 a écrit : j'ai essayé en déclarant fHauteurMur ainsi : float fHauteurMur[10]; et j'ai aussi essayé comme ça : float fHauteurMur[]; |
c'est cHauteurMur qu'il faut modifier ici, hein.
Probablement en posant: char cHauteurMur[13] = "00.0"; (lire plus loin pour l'explication)
Bon, je pense que j'ai une piste, si tu utilises le MikroC de MikroElektronika: La fonction FloatToStr est connue pour avoir des défauts avec certaines versions du compilo, et représenter des nombres (plus grand que 10.0, si ils sont plus petit, il n'y a pas bug semble t'il) qui devraient être avec un chiffre après la virgule comme en ayant plus (dans la string):
Citation : For example try this: |
C'est un bug bien connu apparemment et qui semble se ramener à ceci:
Citation : The FloatToStr function is not the culprit here (it could perform some forced rounding, but it's not a real solution). The source of the problem lies in Microchip floating point library (AN575), used, with some modifications, by mC. Due to errors in original code, the so-called unbiased rounding cannot be used and is blocked in the library. This also means that when converting from float to integral type, there's no rounding, as well - only truncation. These are the real reasons that lead to results with 9's at the end. |
( http://www.mikroe.com/forum/viewto [...] =13&t=9061 )
Si cette fonction buggée fait trop de chiffres après la virgule, ça tiendra pas dans les 5 chars que tu lui donnes avec char cHauteurMur[5] = "00.0"; et c'est peut être ce qui provoque le bug.
Pour vérifier si le pb vient bien de la, remplaces char cHauteurMur[5] = "00.0"; par par cHauteurMur[13] = "00.0"; et regardes si ça colle (apparemment, 13 est la taille approprié pour la chaîne paramètre de FloatToStr selon ce que j'ai lu sur le web)
Certains, pour résoudre le pb d'affichage de juste la partie qui les intéresse et pas tous les chiffres utilisent ce type de technique:
Code :
|
Bref, ils copient les premiers chiffres qu'ils veulent (sans \0 final?), mais en évitant bien d'utiliser la chaine résultat de FloatToStr dans Lcd_Out
D'autres font:
Code :
|
Tu peux sans doute procéder de même en adaptant selon tes besoins.
A+,
Marsh Posté le 26-01-2011 à 19:53:32
ma solution pour le float to string va se résumer à ça :
Code :
|
avec une séparation de deux int pour la partie entière et les décimales ou une adaptation du programme pour gérer les floats
je vais bientot tester si la fonction ne provoque pas de stack overflow (parce que là je l'ai faite dans un programme complètement a part)
je croise les doigts avec ferveur
Marsh Posté le 27-01-2011 à 22:09:53
stack overflow encore, c'est pas possible...
je rêve d'un monde ou la pile n'a pas de limite !
pour faire simple :
CustIntToString fonctionne parfaitement dans un programme pas trop long, même si elle est placée dans 14 boucles while(1) infinies (j'ai essayé !)
par contre si je la place dans le vrai programme (~1000 lignes) que j'ai complètement refait (plus de goto, maximum 5 boucles imbriquées dans le void main et 3 dans les fonctions secondaires), ça me balance un stack overflow directement, quoi que je fasse...
Pour empêcher ce stack overflow je dois pratiquement tout commenter dans CustIntToString (même les lignes du genre "nChiffres++;" ) ET dans Puissance (que j'ai fait parce que la fonction de mikroC faisait une boucle infinie...)
grrr
Marsh Posté le 27-01-2011 à 23:26:16
Il y en a qui avaient écrit leur propre fonction de conversion ici:
http://www.mikroe.com/forum/viewto [...] 88&t=24842
Sinon, en posant en posant: char cHauteurMur[13] = "00.0"; le problème persistait toujours?
A+,
Marsh Posté le 28-01-2011 à 10:00:10
"Sinon, en posant en posant: char cHauteurMur[13] = "00.0"; le problème persistait toujours?"
oui, j'ai essayé [13], [20], [100], []... ça plante toujours...
je vais regarder un peu ce qui a été fait sur le forum de mikroelectronika, merci
Marsh Posté le 23-01-2011 à 10:44:22
Bonjour !
J'ai un problème plutôt agaçant sur un programme en C pour PIC18F452 : Stack overflow is forcing device reset (message donné par ISIS lors de la simulation)
J'ai cherché un peu sur les forums, et il semblerait que cela provienne de trop de boucles les unes dans les autres
ors ce stack overflow n'apparait que quand je met une toute simple ( pBuzzer = 1; ), même pas dans une boucle. (ligne a déjà été utilisée ailleurs sans problèmes...).
Quelqu'un a t'il une idée d'où le problème peut bien venir? des solutions pour limiter/supprimer ce problème?
Merci d'avance !
Message édité par crom29 le 23-01-2011 à 10:50:26
---------------
Mods: HAF922 | Shinobi XL White GitHub Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2