IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

ESP32 C/C++ Tableaux de caractères - plantage après une égalité.


Sujet :

Arduino

  1. #1
    Membre habitué
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    331
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut ESP32 C/C++ Tableaux de caractères - plantage après une égalité.
    Bonjour à tous
    Mon programme fonctionnant avec des String, pour être plus "conforme" aux règles c/c++, j'ai voulu le modifier avec des tableaux de caractères. Et là aie aie aie, ça plante après une égalité. J'essaie d'expliquer tout cela.
    J'ai 3 tableaux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char mpec[10][8];              //10 manips de 0 à 9  8 char par manip  (manip en cours)
    char pg[10][80];               //10 programmes horaire de 10 manips de 8 char
    char memLu[80];               //stockage manips d'un programme horaire enregistré en SPIFFS
    Une commande permet de choisir A pour sélectionner le programme horaire à partir du SPIFFS ou B pour le sélectionner à partir du tableaux des programmes horaires déjà chargé en RAM:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    //***************chargement du programme en cours np[1]=Numéro de Programme**********
    void chargeProgEnCours(char* np){     // 3 P A/B    P=programme  A=lu en SPIFFS   B=lu en RAM
      char fic[8]; sprintf(fic,"/P%c.txt%c",np[1],'\0');    //nom de fichier "/Px.txt"
      progEnCours=ci(np[1]);    //conversion char en numeric
      ok=false;
      uint8_t i,j;
      if(!(progEnCours>=0 && progEnCours<10)){
          afficErreurs(MSG9);
      }    
      else{
        if(np[2]=='A'){           //lecture SPIFFS 80 caractères
          lectureFichier(fic);
          for(i=0;i<10;i++){ 
            for(j=0;j<8;j++){       //mpec = manip en cours
              mpec[i][j]= memLu[i*8 + j];  //0-7 8-15 16-23 ....72-79 charge 10 fois 8 octets dans mpec[0 a 9]  
            }
          }
          for(i=0;i<80;i++){
            pg[progEnCours][i] = memLu[i];    //plantage après i=79
          }
          ok=true;
        }
        else if(np[2]=='B'){    //lecture RAM (80 caractères) 
          for(i=0;i<10;i++){              
            for(j=0;j<8;j++){
              mpec[i][j] = pg[progEnCours][i*8 + j];   //plantage après i=9 j=7
            }
          }
          ok=true;
        }
      }
    }
    Les manip d'un programme horaire sont chargées à la queue leuleu: 0 à 7, 8 à 15, jusqu'à 72 à 79.
    Le plantage réinitialise l'ESP32.
    Dans les deux cas c'est après avoir écrit ou lu la dernière case du tableau pg.
    Une aide serait appréciable. Merci

  2. #2
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 787
    Points : 5 598
    Points
    5 598
    Par défaut
    là c'est déjà un souci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      char fic[8]; sprintf(fic,"/P%c.txt%c",np[1],'\0');    //nom de fichier "/Px.txt"
    sprintf rajoute tout seul un caractère nul à la fin du buffer. votre texte "/Px.txt" fait bien 7 caractères et avec le nul final, ça fait 8 donc ça rentre bien dans l'espace alloué pour fic. Le souci c'est que vous collez un caractère de plus vous même à la fin que vous mettez à '\0' ==> au final sprintf écrit dans le buffer "/Px.txt\0\0" et là ça fait 9 octets et vous avez écrasé quelque chose en mémoire qui va générer un bug ailleurs.

    le mieux c'est de prendre snprintf() car vous ne déborderez pas du buffer;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      char fic[8]; snprintf(fic, sizeof fic, "/P%c.txt",np[1]);    //nom de fichier "/Px.txt"
    ---
    avez vous assez de mémoire pour ces 3 tableaux ? (960 octets - sur un ESP32 ça devrait aller généralement mais ça dépend du reste du code et s'ils sont sur la pile ou si ce sont des variables globales)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char mpec[10][8];              //10 manips de 0 à 9  8 char par manip  (manip en cours)
    char pg[10][80];               //10 programmes horaire de 10 manips de 8 char
    char memLu[80];               //stockage manips d'un programme horaire enregistré en SPIFFS

  3. #3
    Membre habitué
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    331
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    merci Jay M pour cette solution et vous avez raison pour la pile: je viens d'intégrer la fonction complète dans la fonction appelante et je n'ai plus de plantage.
    Une question subsidiaire: pour un tableau de caractères [10][8] doit-on prévoir un caractère nul et donc dimensionner le tableau en [10][9] ? et pour un [10][80] faut-il [10][81] ?

  4. #4
    Membre expérimenté Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    645
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 645
    Points : 1 633
    Points
    1 633
    Par défaut
    Hello,

    Oui, il faut toujours prévoir de l'espace pour le '\0'. Si une chaine de caractères peut contenir jusqu'à 80 caractères, alors il faut la dimensionner à [81] pour le '\0'. Il y a d'ailleurs des programmeurs qui écrivent char buf[80+1]; pour montrer que la chaine peut contenir au maximum 80 caractères, et qu'ils ont pensé à réserver de la place pour le '\0'.
    On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent

  5. #5
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 787
    Points : 5 598
    Points
    5 598
    Par défaut
    la réponse est plus compliquée que cela

    si vous voulez utiliser les fonctions sur les cStrings comme strlen(), strcat() ou même juste print() avec votre tableau de caractère alors il faut absolument un caractère nul à la fin du message car c'est ce qui dit à ces fonctions de s'arrêter / permet de trouver la fin de la chaîne.

    si vous n'utilisez pas ces fonctions et que par exemple vous traitez chaque caractère du tableau individuellement, alors vous n'avez pas besoin du caractère nul.

    en résumé: si votre tableau de caractère est une c-string alors il faut s'assurer qu'il y ait la place pour le caractère nul, sinon c'est un tableau comme un autre, il faut le dimensionner par rapport à son contenu effectif.

    ---

    PS/ aussi attention à la notion de "caractère" versus le nombre d'octets. Des caractères (on dit aussi glyphs ou symboles) comme € î é ô etc vont occuper plusieurs octets en codage UTF8 même s'ils ne représentent qu'un seul symbole à l'écran. Un char c'est un seul octet sur arduino

    ==> donc on ne peut pas faire char message[4+1] = "€ôéç"; même si on ne voit que 4 symboles car ces symboles nécessitent plusieurs octets dans leur représentation.

  6. #6
    Membre habitué
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    331
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 331
    Points : 163
    Points
    163
    Par défaut
    Merci à tous pour ces riches explications.
    Cordialement
    Michel

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Plantage après une boucle, dans le temps.
    Par daerlnaxe dans le forum C#
    Réponses: 3
    Dernier message: 20/04/2018, 13h43
  2. [Tableaux] affichage tableau php apres requete sql count
    Par heteroclite dans le forum Langage
    Réponses: 1
    Dernier message: 13/09/2006, 20h53
  3. plantage après click sur le OK d'une messageBox
    Par cenedra dans le forum MFC
    Réponses: 7
    Dernier message: 31/07/2006, 08h43
  4. Réponses: 6
    Dernier message: 15/06/2006, 12h56
  5. [Tableaux] Réorganiser un tableau apres un merge()
    Par Death83 dans le forum Langage
    Réponses: 3
    Dernier message: 07/01/2006, 01h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo