Subtilité des pointeur de char

Bonjour,
Je rencontre un problème avec 'char*':
J'ai une fonction boolean qui reçois une chaine par le biais de l'UDP, et renseigne une variable global (déclarée en début de code) 'char* read'.

Une fois cette étape passé, au retour dans ma loop (ou ailleurs), il semble que read ne pointe plus au bon endroit. comme si l'adresse était écrasé à la sortie de la fonction 'UdpReceive()'.

Il doit y avoir encore un truc tout bête...

Mon code:

boolean UdpReceive() {
  read = "";
  int packetSize = Udp.parsePacket();
  delay(100);
  if (packetSize)
  {
    IPAddress remoteIp = Udp.remoteIP();
    whoTalk = remoteIp[3];

    // Message reçu
    char packetBuffer[packetSize + 1];
    Udp.read(packetBuffer, packetSize);
    packetBuffer [packetSize] = '\0';
    read = (char *)packetBuffer;

    return (true);
  }
  return (false);

}

Salut

Normal :

    char packetBuffer[packetSize + 1];
    // plutôt
    static char packetBuffer[packetSize + 1];

il me donne l'erreur suivante la compilation:
storage size of 'packetBuffer' isn't constant

pareil en déclarant:
const int packetSize = Udp.parsePacket();

En plus , Udp.read(char, int) voir Ethernet - Arduino Reference

Ce n'est pas possible de dimensionner un tableau comme cela avec une variable.
Tu vas être obligé de dimensionner ce tableau avec une constante, en considérant la taille maximale des données que tu dois recevoir.

EDIT

Dans l'exemple de la doc, UDP_TX_PACKET_MAX_SIZE est utilisé.
Essaie d'afficher sa valeur.

@+

'UDP_TX_PACKET_MAX_SIZE', ce doit être le truc bête dont je parlais dans mon 1er message.
Ça à l'aire d'aller mieux!
Merci, je vai regarder plus loin dans mon code, il doit y avoir encore un autre bug sur les pointeurs...

Zarb94:
Bonjour,
Je rencontre un problème avec 'char*':
J'ai une fonction boolean qui reçois une chaine par le biais de l'UDP, et renseigne une variable global (déclarée en début de code) 'char* read'.

Une fois cette étape passé, au retour dans ma loop (ou ailleurs), il semble que read ne pointe plus au bon endroit. comme si l'adresse était écrasé à la sortie de la fonction 'UdpReceive()'.

Ne jamais oublier que char* toto ne réserve aucun espace pour stocker la chaîne de caractères. Et que la chaîne packetBuffer est locale à la fonction UdpReceive() elle est donc créée sur la pile et elle est perdue en quittant la fonction.

fdufnews:
Ne jamais oublier que char* toto ne réserve aucun espace pour stocker la chaîne de caractères. Et que la chaîne packetBuffer est locale à la fonction UdpReceive() elle est donc créée sur la pile et elle est perdue en quittant la fonction.

c'est bien pour ça que hbachetti parlait de déclarer packetBuffer en "static"

Oui mais un peu rapidement.
Je n'avais pas vu que le tableau était dimensionné à l'aide d'une variable.

@+

bricofoy:
c'est bien pour ça que hbachetti parlait de déclarer packetBuffer en "static"

Je ne remets pas en cause ce qu'a dit hbachetti. J'explique pourquoi il faut le faire.

Pas de problème ... J'ai donné la réponse toute faite, fdufnews a pris le temps d'expliquer pourquoi il fallait le faire.

@+

fdufnews:
Ne jamais oublier que char* toto ne réserve aucun espace pour stocker la chaîne de caractères. Et que la chaîne packetBuffer est locale à la fonction UdpReceive() elle est donc créée sur la pile et elle est perdue en quittant la fonction.

Bonjour fdufnews,
Je savais qu'elle serait perdu en sortant, c'est pourquoi je fais une copie dans read. La suite de mon code transmet 'read' avec 'Analyse(read)' à la fonction Analyse

void Analyse(char* analyse)
{
  Serial.println("Fonction: Analyse");
   const char s[2] = "\t";                                  // Séparateur recherché
  char* buffer;                                             // Création du buffer qui contiendra l'argument extrait
  buffer = strtok (analyse, s);                             // Récupère le 1er argument
  int i = 0;                                                // initialise un compteur
  while (buffer != NULL)                                    // Tant que buffer ne contiens pas le char 'nul' il reste des arguments
  {
    //Serial.print("buffer: "); Serial.println(buffer);
    Recu[i] = buffer;                                       // Sauvegarde l'argument extrait
    buffer = strtok (NULL, s);
    i++;
  }
  return;
}

Dans cette fonction je reprend encore la copie du pointeur du buffer de 'UdpReceive()', et là je découpe la chaine en plusieurs morceaux dans 'char* Recu. Je travaille donc toujours avec des pointeurs.
Sans explication, dans la fonction suivante (qui n'est pas encore finalisée), je perd le pointeur 'Recu[0]'

// Boucle de recherche ligne par lignevoid find_BDD()
void find_BDD()
{
  Serial.println(F("Fonction: find_BDD()"));
    char buffer[120];                                                             // Buffer d'extraction
    char* pch;                                                                // buffer de récupération
    int cont = 0;                                                             // Nb de char lue
    int pos_tab = 0;                                                          // Position des éléments trouvé dans le tableau 'find_BDD'


    // Ouvre la base de donnée
    File myFile = SD.open(Fichier, FILE_READ);
    if (myFile)
    {
      //------------------------------------------------
      while (pch != Recu[0])/* Recu[0] = Marqueur recherché  */
      {
        if (myFile.available() > 0)
        {
          myFile.seek(pos);
          cont = 0;
          
          // Recupere une ligne entiere-----------------
          while ((buffer[cont++] = myFile.read()) != '\n')     // ici, j'ai perdu le pointeur Recu[0]
          {}

          BDD_LigneAnalysee = pos;
          pos = myFile.position();
          buffer[cont++] = '\0'; 
          
          // Traitement de la ligne---------------------
          if (buffer[0] != '/' && buffer[0] != '\n')
          {
            //pch = strtok ((char*)buffer, "\t"); // cette ligne provoque un crash!
          }
        }
        else break;
      }
    }
    else
    {
      Serial.println("Erreur de lecture carte SD!");
    }
  while (1 == 1)  // STOP!
  {
    
  }
}

Je savais qu'elle serait perdu en sortant, c'est pourquoi je fais une copie dans read. La suite de mon code transmet 'read' avec 'Analyse(read)' à la fonction Analyse

    read = (char *)packetBuffer;

Je suppose que read est un pointeur. Donc tu lui colle l'adresse d'un buffer sur la pile (packetBuffer), qui sera perdu en sortant de la fonction.
Donc cela revient au même.

Le raisonnement de fdufnews est tout à fait valable, pointeur intermédiaire ou pas.

@+

Voila,
il y a encore un bug, si je fais disparaitre la ligne ' Serial.print(TabDeChar[q]);' alors, char TabDeChar ne s'affiche pas.

Dans ma loop:

  Serial.println(F("Creation dun pounteur de char* et \nle copie dans un tableau de char de la meme taille\n"));
  char* PointeurDeChar;                       // = Pointeur sur un String
  PointeurDeChar = "Ceci est le message contenu dans \nla ligne visé par le pointeur char* PointeurDeChar\n";

 PointeurVersTabChar(PointeurDeChar);//, TabDeChar);//, TabDeChar[120])
  
  Serial.println(F("Apres la fonction:\n------------------"));
  Serial.print(F("\nchar* PointeurDeChar= ")); Serial.println(PointeurDeChar);
  Serial.print(F("\nchar TabDeChar [i]= ")); Serial.println(TabDeChar);

La fonction:

char PointeurVersTabChar(char* Entree)//, char &Sortie[])//[120]);
{
  int q;
  while (Entree[q] != '\0')
  {
    TabDeChar[q] = Entree[q];
    q++;
    
  Serial.print(TabDeChar[q]);
  }
  TabDeChar[q+1] = '\0';
  //Serial.print(F("\nDepuis la fonction, char TabDeChar [i]= ")); Serial.println(TabDeChar);
  return;
}

Faudrait peut-être initialiser q