Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Pages: [1]   Go Down
Author Topic: Pourquoi ma variable est detruite au fure et a mseure  (Read 840 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour à tous,

Je suis sur un truc de fou mais je m'en sors avec perséveration  smiley.
Je suis pas trop expérimente c'est surement pourquoi, je prends tant de temps.....

J'ai une fonction qui doit me retourner un array. Je la declare comme ceci

Code:
char * getGPSCoords(void){
   // Je ne mets oas tous le code, a moins que vous en avez besoin.
   // Cette fonction fait appele a une autre pour collecter des positions GPS que je fusionne en une fonction. Etant donné que les valeurs et la longueur des valeur change, je calcule la taille de ces variable ainsi:


   // Je calcule la taille de toute les variables utilisée dans coords
   int le = strlen(lo)+strlen(la)+strlen(al)+strlen(ti)+strlen(ve)+strlen(en)+strlen(lon)+strlen(lat)+strlen(alt)+strlen(vel)+strlen(time);
   char coords[le];  
   /*
   char * coords;
   coords = (char*) malloc (le+1);
   */
   // C'est pourcela que je declare coords dans cette function car le peut changer et ainsi je suis sure de toujours avoir la taille de l'array en fonction des longeurs de toutes les variables correspondant aux positions GPS


   // A la fin je retourn coords pour l'exploiter plus loin
   // coords retournera 'lo=0.000000&la=0.000000&al=0.000000&ti=20130714213222.000&ve=0.000000'. Les zero, parce que je suis a un endorit qui ne choppe pas les positions, mais ca c'est pas grave pour le moment.
   return coords;
}

J'ai ensuite une action qui va envoyer les positions sur une base MySQL en POST, et c'est que les problèmes commencent.

Code:
// SEND DATA
// Quand je tape "send" dans mon terminal, il effectue ce code:
if(!strcmp(inSerial,"send")){
   #ifdef DEBUG
      Serial.println(F(""));
      Serial.println(F("SENDING COORDS TO THE REMOTE SERVER"));
      Serial.println(F("---------------------------------------"));
   #endif
        
   // Ceci affiche la valeur de mon array coords
   // Resultat : lo=0.000000&la=0.000000&al=0.000000&ti=20130714213222.000&ve=0.000000 (Dans le cas actuel, mon GPS ne capte pas de position, mais ca c'est pas grave pour le moment.
   Serial.println(getGPSCoords());


    // Ici c'est la fonction qui va envoyer "lo=0.000000&la=0.000000&al=0.000000&ti=20130714213222.000&ve=0.000000
" au serveur, et la les problème commence
    inet.httpPOST(host, port_post, path_post, getGPSCoords() , "Result", 4000);
    delay(10000);
 
}
Ici la fonction httpPOST(host,port_post, getGPSCoords,"Result",400). Je n'ai pas fait cette fonction. C'est une librairie que j'ai trouvé et qui semble pas mal...
Les problèmes commencent... et c'est peut etre tout simple à résoudre, mais j'ignore la parade.

NOTEZ BIEN que plus haut, Serial.println(getGPSCoords()), affiche bien ce que j'ai besoin, soit
Quote
lo=0.000000&la=0.000000&al=0.000000&ti=20130714213222.000&ve=0.000000

Le problème qu'au fure et à mesure que je fais un Serial.print(parameters), voir ci dessous, ma valeure
lo=0.000000&la=0.000000&al=0.000000&ti=20130714213222.000&ve=0.000000
est tronqué. Je perds des chifres.

Je mets le code de httpPOST(host,port_post, getGPSCoords,"Result",400) dans un reply afin d'avoir la place
« Last Edit: July 15, 2013, 10:20:59 am by pierrot10 » Logged

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!

Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai mis un commentaire à côte des
Quote
Serial.println(parameters);
Code:
int InetGSM::httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength)
{
        Serial.println(F("Starting to send"));
Serial.println(parameters); // Ceci lo=0.000000&la=0.000000&al=0.000000&ti=20130714213229.!Û%

Serial.println(parameters); // ceci lo=0.000000&la=0.000000&al=0.000000&ti=20130714213229.

  
  boolean connected=false;
  int n_of_at=0;
  char itoaBuffer[8];
  int num_char;
  char end_c[2];
  end_c[0]=0x1a;
  end_c[1]='\0';

  while(n_of_at<3){
 if(!connectTCP(server, port)){
  #ifdef DEBUG_ON
Serial.println("DB:NOT CONN");
#endif
    n_of_at++;
 }
 else{
connected=true;
n_of_at=3;
}
  }

  if(!connected){
   Serial.println(F("Not connected"));
   return 0;
  }

Serial.println(parameters); // Ceci affiche  : Ê
Serial.println(parameters); // Ceci affiche encore : Ê


  gsm.SimpleWrite("POST ");
  gsm.SimpleWrite(path);
  gsm.SimpleWrite(" HTTP/1.1\nHost: ");
  gsm.SimpleWrite(server);
  gsm.SimpleWrite("\n");
  gsm.SimpleWrite("User-Agent: Arduino\n");
  gsm.SimpleWrite("Content-Type: application/x-www-form-urlencoded\n");
  gsm.SimpleWrite("Content-Length: ");
  itoa(strlen(parameters),itoaBuffer,10);
  gsm.SimpleWrite(itoaBuffer);
  gsm.SimpleWrite("\n\n");
  gsm.SimpleWrite(parameters);
  gsm.SimpleWrite("\n\n");
  
  gsm.SimpleWrite(end_c);
 
 Serial.println(parameters); // et  Ceci affiche encore : Ê
 Serial.println(parameters); / et encore  Ceci affiche encore : Ê....
 
  switch(gsm.WaitResp(10000, 10, "SEND OK")){
case RX_TMOUT_ERR:
return 0;
break;
case RX_FINISHED_STR_NOT_RECV:
return 0;
break;
  }

 delay(50);
#ifdef DEBUG_ON
Serial.println("DB:SENT");
#endif

  int res= gsm.read(result, resultlength);
  Serial.println(F("Data sent"));
  
  //gsm.disconnectTCP();
  return res;
}

Selon les commentaire que j'ai mis dans le code, pourquoi 'parameters' perds sa valeurs???? alors qu'elle devrait rester
lo=0.000000&la=0.000000&al=0.000000&ti=20130714213222.000&ve=0.000000

Es-ce que j'ai fait un truc de faux dans ma function getGPSCoords() lorsque je retourne coords (return coords;)?

J'ai entendu parler de la declarer en static ou d'utiliser malloc(), mais la je suis largué car il faut que la taille de  char coords[] puisse s'adapter en fonction des tailles des positions GPS.

J'espère que vous m'avez compris et que j'ai été claire et si vous arriviez à me dépanner ca serat d'une très grande utilité!!

Milles mercis

Dite moi si vous avez besoin plsu de code!!!
« Last Edit: July 15, 2013, 10:43:19 am by pierrot10 » Logged

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!

France
Offline Offline
Faraday Member
**
Karma: 40
Posts: 3660
There is an Arduino for that
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

2 problèmes:
  1) coords est définie dans la fonction getGPSCoords donc elle est locale à cette fonction et elle est détruite aussitôt que tu quittes getGPSCoords.
  2) tu fais un malloc dans getGPSCoords mais tu ne libères jamais cette zone mémoire donc tu as une fuite mémoire puisqu'à chaque appel tu refais l'allocation d'un buffer que tu ne libères jamais.

Le pointeur est bien retourné par getGPSCoords et il est donc récupéré par la fonction appelante.Il faudrait donc libérer l'espace occupé par coords lorsque tu quittes getGPSCoords et  faire un strcpy pour récupérer la chaîne pointée.

Sur des petites architectures comme l'arduino, je pense qu'il est préférable de créer un scratchpad en global de taille correcte qui servira de buffer à tout le monde (cela oblige à une certaine discipline dans son utilisation).
Logged

Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut merci pour ta reponse.

Je ne fais pas malloc, il est commenté.
Je l'ai mis en commentaire parce que ca génère une erreur.
j'ai deja essayé strcpy mais encore ca fait une erreur.
Je t'avoir etre suis un peu largé. Pourrais je te demander un exemple?

Je ne suis pas habitué au manipulation...

Un grand merci

« Last Edit: July 15, 2013, 01:36:23 pm by pierrot10 » Logged

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!

Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Voici ma fonction
Code:
char * getGPSCoords(void){
 
  #ifdef DEBUG
    stat=gps.getStat();
    if(stat==1){
      Serial.println(F("NOT FIXED"));
    }else if(stat==0){
      Serial.println(F("GPS OFF"));
    }else if(stat==2){
      Serial.println(F("2D FIXED"));
    }else if(stat==3){
      Serial.println(F("3D FIXED"));
    }
    delay(5000);
  #endif   
 
  //Get data from GPS
 
   gps.getPar(lon,lat,alt,time,vel);
 
  char lo[]="lo=";
  char la[]="&la=";
  char al[]="&al=";
  char ti[]="&ti=";
  char ve[]="&ve=";
  char en[]="\0";
 
 
  #ifdef DEBUG

  #endif
 
  int le = strlen(lo)+strlen(la)+strlen(al)+strlen(ti)+strlen(ve)+strlen(en)+strlen(lon)+strlen(lat)+strlen(alt)+strlen(vel)+strlen(time);
  /*
  char * coords;
  coords = (char*) malloc (le+1);
 */
 
  char coords[le];
 
  strcpy(coords,lo);
  strcat(coords,lon);
 
  strcat(coords,la);
  strcat(coords,lat);
 
  strcat(coords,al);
  strcat(coords,alt);

  strcat(coords,ti);
  strncat(coords,time,14);
 
  strcat(coords,ve);
  strcat(coords,vel);
 
  strcat(coords,en);
  /*
  #ifdef DEBUG
    Serial.print(F("Coords : "));                               
    Serial.println(coords);
   // Serial.println(strlen(coords));
  #endif
  */
 
  return coords;

}
Logged

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!

France
Offline Offline
Faraday Member
**
Karma: 40
Posts: 3660
There is an Arduino for that
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
 int le = strlen(lo)+strlen(la)+strlen(al)+strlen(ti)+strlen(ve)+strlen(en)+strlen(lon)+strlen(lat)+strlen(alt)+strlen(vel)+strlen(time);
  
  char coords[le];

Ceci n'est pas autorisé. La taille des tableaux doit être connue à la compilation. Or à ce moment là le=0 donc tableau de taille nulle. C'est la porte ouverte à un gros plantage.
Pour faire de l'allocation dynamique il faut impérativement passer par les pointeurs.


Un exemple qui fonctionne semble-t-il comme tu le voudrais
Quote

#include "Arduino.h"
char lon[15];
char lat[15];
char alt[15];
char time[20];
char vel[15];
char buffer[150];

// créée pour les besoin de l'essai car je n'ai pas la librairie gps
void getPar(char*a, char* b, char* c, char* d, char* e){
  
  strcpy(a,"13.122545");
  strcpy(b,"3.254568");
  strcpy(c,"13245");
  strcpy(d,"15-7-2013 23:22:45"); // la chaine fait plus de 14 caractères
  strcpy(e,"135");
}

char * getGPSCoords(void){
 
  #ifdef DEBUG
    stat=gps.getStat();
    if(stat==1){
      Serial.println(F("NOT FIXED"));
    }else if(stat==0){
      Serial.println(F("GPS OFF"));
    }else if(stat==2){
      Serial.println(F("2D FIXED"));
    }else if(stat==3){
      Serial.println(F("3D FIXED"));
    }
    delay(5000);
  #endif    
  
  //Get data from GPS
  
   getPar(lon,lat,alt,time,vel);  // remplace gps.getPar()
  
  char lo[]="lo=";
  char la[]="&la=";
  char al[]="&al=";
  char ti[]="&ti=";
  char ve[]="&ve=";
  char en[]="\0";
  
  
  #ifdef DEBUG

  #endif
  
  // buffer suffisament large pour contenir la chaine finale
  // la place sera libérée en quittant la fonction donc ce n'est pas trop grave
  char coords[150];      
  
  strcpy(coords,lo);
  strcat(coords,lon);
 
  strcat(coords,la);
  strcat(coords,lat);
  
  strcat(coords,al);
  strcat(coords,alt);

  strcat(coords,ti);
  strncat(coords,time,14);  // là tu tronques la chaine à 14 caractères on le voit dans la chaine finale la fin est coupée
  
  strcat(coords,ve);
  strcat(coords,vel);
  
  strcat(coords,en);
  /*
 #ifdef DEBUG
   Serial.print(F("Coords : "));                              
   Serial.println(coords);
  // Serial.println(strlen(coords));
 #endif
 */
  return coords;

}

void setup(void){
  Serial.begin(9600);
  strncpy(buffer,getGPSCoords(),149);
  Serial.println(buffer);
  Serial.println("Going into loop");
}

void loop(void){
  strncpy(buffer,getGPSCoords(),149);
  Serial.println(buffer);
  delay(100);
}

« Last Edit: July 15, 2013, 02:59:59 pm by fdufnews » Logged

Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci beaucoup,
J'ai changé un peu mon coce, car j'avais fait trop compliquéet j'ai refait plus simple.
Mais ton exemple me sera fort utile et je prendrai le temps de le lire en entier.

Par contre je deviens fou et je crois qe j'ai des gros probleme a comprendre l'allocation des tailles pour un char.

Quand je tape 'send' dans mon terminal,
Serial.println(coords); affiche bien ca
Quote
lo=608.482777&la=4613.163541&al=459.471680&ti=20130715215238&ve=0.000000
Ce qui me rend fou, c'est quand je decommente ceci
Code:
Serial.println(strlen(coords));

mon programme plante.

Et j'ai pourtant change, comme tu l'a suggéré plus haut ceci
Code:
char coords[150];
mais ca ne vas pas mieux

J'ai refait mon code aisni:
Code:

// Ceci est aussi déclaré plus haut
char lon[15];
char lat[15];
char alt[15];
char time[14];
char vel[15];
char msg1[5];
char msg2[5];

char lo[]="lo=";
char la[]="&la=";
char al[]="&al=";
char ti[]="&ti=";
char ve[]="&ve=";
char en[]="\0";


    // SEND DATA
    if(!strcmp(inSerial,"send")){
        #ifdef DEBUG
          Serial.println(F(""));
          Serial.println(F("SENDING COORDS TO THE REMOTE SERVER"));
          Serial.println(F("---------------------------------------"));
        #endif
       
        #ifdef DEBUG
          stat=gps.getStat();
          if(stat==1){
            Serial.println(F("NOT FIXED"));
          }else if(stat==0){
            Serial.println(F("GPS OFF"));
          }else if(stat==2){
            Serial.println(F("2D FIXED"));
          }else if(stat==3){
            Serial.println(F("3D FIXED"));
          }
          delay(5000);
        #endif   
 
        //Get data from GPS
        /*
        memset(&lon, 0 , sizeof(lon));
        memset(&lat, 0 , sizeof(lat));
        memset(&alt, 0 , sizeof(alt));
        memset(&time, 0 , sizeof(time));
        memset(&vel, 0 , sizeof(vel));
        */
        gps.getPar(lon,lat,alt,time,vel);
     
        //char coords[150];
        char coords[97];
       
        //memset(&coords, 0 , sizeof(coords));
       
       
        strcpy(coords,lo);          //3
        //strncat(coords,lon,15);    //18
        strcat(coords,lon);
 
        strcat(coords,la);         //22
        //strncat(coords,lat,15);    //37
        strcat(coords,lat);
 
        strcat(coords,al);         //41
        //strncat(coords,alt,15);    //56
        strcat(coords,alt);

        strcat(coords,ti);         //60
        strncat(coords,time,14);   //74
        //strcat(coords,time);
 
        strcat(coords,ve);         //78
        //strncat(coords,vel,15);    //93
        strcat(coords,vel);
 
        strcat(coords,en);       //95
       
        Serial.println(coords);

      //  Serial.println(strlen(coords));
/*       
        inet.httpPOST(host, port_post, path_post, coords, "Result", 50);
   */     
        delay(10000);
       
        enterCommand();
    }

Pourquoi ca plante??? smiley-cry
« Last Edit: July 15, 2013, 05:34:50 pm by pierrot10 » Logged

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!

france
Offline Offline
God Member
*****
Karma: 15
Posts: 894
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ce qui me rend fou, c'est quand je décommente ceci
Code:
Serial.println(strlen(coords));
mon programme plante.
strlen cherche sans doute un caractère NUL en fin de chaîne sans le trouver ?
Logged

Christian

Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ha mais j'ai lu de la doc qui dit que la fonction strcat() écrase le caratere NUL (\n) et le rajoute apres, après la cacetanation.
M'es-ce pas ca?
Logged

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!

Pages: [1]   Go Up
Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Jump to: