erreur avec des char*

erreur avec des char* - C - Programmation

Marsh Posté le 16-12-2006 à 19:41:27    

Bonjour,
   pour un projet en Reseau, je dois écrire un protocole (minimaliste) pour faire communiquer des machines sur une architecture logicielle du type token-ring. Bon pour le moment j'essaie déjà avec 2 PC  :D (enfin 2 processus sur le même PC). Voila une partie de mon code :
 
La structure paquet, dans laquelle je met toutes mes donnée sous forme de char*

Code :
  1. typedef struct    //definition de la structure paquet
  2. {
  3.     unsigned int numeroDest;  //numero du destinataire
  4.     unsigned int numeroEmmeteur; //numer de l'emmeteur
  5.     unsigned int flag;   //info complementaire : 0 paquet de donne, 1 paquet de confirmation, 2 paquet pour passer la main
  6.    
  7.     unsigned int tailleDonne;  //taille des donnes
  8.     char* data;    //les donnes
  9. }paquet;


ma méthode pour mettre les données dans le paquet :

Code :
  1. paquet *creePaquet(char* chaine, int dest, int emm) //remplit les champs
  2. {
  3.     paquet *p;
  4.     p = malloc(sizeof(paquet));
  5.     p->numeroDest = dest;
  6.     p->numeroEmmeteur = emm;
  7.     p->flag = 0;
  8.     p->tailleDonne = strlen(chaine)+1;
  9.     p->data = malloc(strlen(chaine)+1);
  10.     strcpy(p->data, chaine);
  11.     return p;
  12. }


et voila pour l'envois et la reception :

Code :
  1. bool emission(char *chaine, int dest, int source, int priseEmission, int priseReception)
  2. {
  3.     paquet *donne;   //pointeur sur le paquet qui va etre emmis
  4.     char *t;    //pointeur pour la verification
  5.     unsigned int temp;   //on memorise la valeur d'une donne
  6.     char buffer[256];
  7.    
  8.     donne = creePaquet(chaine, dest, source); //creation du paquet
  9.     envoie(priseEmission, (char *) donne, sizeof(paquet)+donne->tailleDonne*sizeof(char));//envoie le paquet
  10.     printf("taille d'un paquet : %d\n", sizeof(paquet));
  11.     printf("taille de mes donne : %d\n", sizeof(paquet)+donne->tailleDonne*sizeof(char));
  12.     free(donne->data);//liberation de la mem allouée
  13.     free(donne);
  14.     memset(buffer, '\0', sizeof(buffer));//on se prepare a reecouter
  15.     recoit(priseReception, buffer, sizeof(buffer)-1);
  16.     t = buffer;
  17.    
  18.     temp = *(unsigned int*) t; //on cherche qui est le destinataire
  19.     if(temp == source)//on rergarde si le paquet nous est destine
  20.     {
  21.         t += sizeof(unsigned int);//on regade si c'est le paquet dont on attend la confirm
  22.     temp = *(unsigned int*) t;
  23.         if(temp == dest)
  24.         {
  25.         t += sizeof(unsigned int);
  26.             temp = *(unsigned int*) t;
  27.             if(temp == 1)//on regarde si le paquet est bien pour confirmer
  28.                 return true;   
  29.         }
  30.        
  31.     }
  32.     return false;
  33. }
  34. char *reception(int dest, int source, int priseEmission, int priseReception)
  35. {
  36.     paquet *donne;
  37.     char buffer[256];
  38.     char *t;
  39.     unsigned int destinataire;
  40.     unsigned int emmeteur;
  41.     unsigned int flag;
  42.     unsigned int taille;
  43.    
  44.     memset(buffer, '\0', sizeof(buffer));
  45.    
  46.     recoit(priseReception, buffer, sizeof(buffer)-1);
  47.     t = buffer;
  48.    
  49.     destinataire = *(unsigned int*) t; //on cherche qui est le destinataire
  50.     t += sizeof(unsigned int);
  51.     emmeteur = *(unsigned int*) t;//on regade qui envois le paquet
  52.     t += sizeof(unsigned int);
  53.     flag = *(unsigned int*) t; //on regarde le type de paquet
  54.     t += sizeof(unsigned int);
  55.     taille = *(unsigned int*) t;//on regarde la taille du paquet
  56.     t += sizeof(unsigned int);
  57.    
  58.     if(destinataire != source) //si le paquet nous est pas destine on le renvoie
  59.     {
  60.         envoie(priseEmission, buffer, sizeof(paquet)+taille*sizeof(char));
  61.     return reception(dest, source, priseEmission, priseReception);//et on reecoute
  62.     }
  63.     else
  64.     {
  65.         if(flag == 0)  //ce sont des donne pour nous
  66.         {
  67.             char *data;
  68.             data = malloc(taille*sizeof(char));
  69.             memset(data, '\0', taille*sizeof(char));
  70.         strcpy(data, t);  //on les prends
  71.    
  72.             donne = confirme(emmeteur, source); //on confirme la reception  
  73.             envoie(priseEmission, (char *)donne, sizeof(paquet));
  74.             free(donne); 
  75.             return data;
  76.         }
  77.         if(flag == 2)
  78.             printf("on prend la main \n" );
  79.         return "";
  80.     }
  81. }


 
bon, le problème c'est que quand j'affiche le résultat de la fonction reception, la chaine de caractère ne s'affiche pas... (il affiche n'importe quoi...) et là ça fait quelques heures que je suis dessus et je vois pas... tout le reste fonctionne : je reçoit bien tous les autres variables de ma structure paquet mais pas la chaine... Et en plus le dialogue entre mes deux processus marche niquel. il y a juste que j'arrive pas a avoir ma chaine. (je suis quasi sur que doit manquer un +1 quelque part pour une copie, ou une allocation... je vois que que ça pourrais être que ça... mais je vois pas..) si vous avez une idée ?
 
Merci :)


Message édité par Amonchakai le 16-12-2006 à 19:44:32
Reply

Marsh Posté le 16-12-2006 à 19:41:27   

Reply

Marsh Posté le 16-12-2006 à 19:42:56    

Tu cast pas le retour de malloc ?

Reply

Marsh Posté le 16-12-2006 à 19:46:12    

ben, non. j'avais lu a plusieurs reprise que ce n'étais pas obligé. Et que ça n'avais jamais fait parti du standard de caster le retour du malloc....
[edit] j'avais lu ça la : http://mapage.noos.fr/emdel/notes.htm


Message édité par Amonchakai le 16-12-2006 à 19:52:15
Reply

Marsh Posté le 16-12-2006 à 22:35:02    

_darkalt3_ a écrit :

Tu cast pas le retour de malloc ?

Par contre c'est pas mal de tester le retour de malloc ! Et aussi, sizeof(char) == 1 par défintion.
Je vais sans doute dire une co***rie car je n'y connais rien dans ce domaine, mais j'ai quand même l'impression que tu n'envoies pas de message car ton p->data est simplement un pointeur alloué ailleurs ,ce qui fait que tu envoies une adresse et sans doute n'importe quoi avec, mais pas le message.


Message édité par Trap D le 16-12-2006 à 22:44:48
Reply

Marsh Posté le 17-12-2006 à 09:53:46    

Ok, merci
 
    bon, comme tout le monde a l'air d'insister sur le fait qu'il faut mettre des cast devant le malloc je les aient rajoutés.  
   Sinon, en ce qui conserne mon problème je pense que tu as raison : j'utilise la memoire de mes paquets comme si elle était continue, alors que je fais deux allocations distinctes... donc j'ai remplacé mes deux allocations par ça :

Code :
  1. p = (paquet *) malloc(sizeof(paquet)+strlen(chaine)+1);


mais le truc c'est que j'ai le droit au bon vieux segmentation fault (si cher à Linux...) au moment ou je fait ensuite le strcpy(p->data, chaine);
 
enfin, la je devrais trouver...
Merci :)

Reply

Marsh Posté le 17-12-2006 à 10:05:07    

A toi de trouver à quelle adresse exacte se réfère le p->data...
A mon avis, il faut "oublier" le p->data et copier les données à un offset précis du paquet : p+4*sizeof(unsigned int) par exemple.
PS : on s'est mal compris, en C (pas en C++) le cast est déconseillé car il masque l'oubli de l'inclusion du header de déclaration de malloc.

Reply

Marsh Posté le 17-12-2006 à 10:19:06    

ok, désolé. j'avais mal lu ton post : j'étais en train de penser au cast et voila...
Donc oui tu as raison, je vais tester le retour des malloc :D. sinon merci car maintenant j'ais plus le segmentation fault

Reply

Marsh Posté le 17-12-2006 à 11:03:26    

Amonchakai a écrit :

   bon, comme tout le monde a l'air d'insister sur le fait qu'il faut mettre des cast devant le malloc je les aient rajoutés.


C'est pas 'tout le monde', loin de là. Tu as eu tord...

Citation :


   Sinon, en ce qui conserne mon problème je pense que tu as raison : j'utilise la memoire de mes paquets comme si elle était continue, alors que je fais deux allocations distinctes... donc j'ai remplacé mes deux allocations par ça :

Code :
  1. p = (paquet *) malloc(sizeof(paquet)+strlen(chaine)+1);


mais le truc c'est que j'ai le droit au bon vieux segmentation fault (si cher à Linux...) au moment ou je fait ensuite le strcpy(p->data, chaine);


Encore faut-il déclarer la structure correctement, par exemple :  

Code :
  1. struct paquet
  2. {
  3.    T entetes;
  4.    char donnees[1];
  5. };


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 17-12-2006 à 11:41:13    

Salut,
 
   tout d'abord merci de ton aide. bon, j'ai bien retiré les cast après les malloc
   Mais j'avoue qu'il y a un truc qui me chagrine dans ce que tu écris : tu fais  
 

Code :
  1. typedef struct    //definition de la structure paquet
  2. {
  3.     unsigned int numeroDest;  //numero du destinataire
  4.     unsigned int numeroEmmeteur; //numer de l'emmeteur
  5.     unsigned int flag;   //info complementaire : 0 paquet de donne, 1 paquet de confirmation, 2 paquet pour passer la main
  6.    
  7.     unsigned int tailleDonne;  //taille des donnes
  8.     char donne[1];    //les donnes
  9. }paquet;
  10. }

 
 
et ensuite tu fais le malloc, puis la copie ?  

Code :
  1. p = malloc(sizeof(paquet)+strlen(chaine)+1);
  2. strcpy(p->donne, chaine);


ce que je comprend pas c'est que donne est un pointeur constant donc d'après ce que j'avais toujours compris on ne peut pas le faire pointer sur un autre espace mémoire déterminé par malloc...
 
si tu pourrais m'éclairer la dessus ça serai sympa.
 
Merci :)

Reply

Marsh Posté le 17-12-2006 à 12:05:06    

Amonchakai a écrit :


   tout d'abord merci de ton aide. bon, j'ai bien retiré les cast après les malloc
   Mais j'avoue qu'il y a un truc qui me chagrine dans ce que tu écris : tu fais

 

et ensuite tu fais le malloc, puis la copie ?

 

ce que je comprend pas c'est que donne est un pointeur constant donc d'après ce que j'avais toujours compris on ne peut pas le faire pointer sur un autre espace mémoire déterminé par malloc...


Oui, c'est une possibilité un peu 'exotique' offerte indirectement par le langage qui a d'ailleurs été entérinée en C99 avec

Code :
  1. struct paquet
  2. {
  3.    T entetes;
  4.    char donnees[0];
  5. };


L'idée, est d'utiliser une structure pour définir un bloc linéaire de longueur variable. Le début de la structure est défini, et la fin est un tableau (ici, de char). On défini une taille sans signification réelle (1 en C90, 0 en C99) qui permet simplement à la syntaxe tableau de s'appliquer pour accéder aux données. On fait ouvertement un dépassement de tableau, et on a donc intérêt à savoir ce qu'on fait, car évidemment, aucun contrôle n'est possible.

 

Je prends un exemple simple :

Code :
  1. struct tableau
  2. {
  3.    size_t size;
  4.    int a[1];
  5. };
  6. /* creation d'un tableau lineaire de 3 int : */
  7.    size_t n = 3;
  8.    struct tableau *p = malloc (sizeof *p + sizeof *p->a * n);


Message édité par Emmanuel Delahaye le 17-12-2006 à 12:05:57

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 17-12-2006 à 12:05:06   

Reply

Marsh Posté le 17-12-2006 à 12:37:28    

ok, j'ai compris  
 
Merci :)

Reply

Marsh Posté le 17-12-2006 à 22:28:03    

_darkalt3_ a écrit :

Tu cast pas le retour de malloc ?


 :non:  on ne cast pas un retour de malloc en C. C'est lourd, inutile et redondant.
Et en C++, on utilise new.

Reply

Marsh Posté le 20-12-2006 à 13:50:39    

jesus_christ a écrit :

:non:  on ne cast pas un retour de malloc en C. C'est lourd, inutile et redondant.
Et en C++, on utilise new.


 
et le compilo ne te ponds pas une erreur du style
"[...] without a cast" ??
 

Reply

Marsh Posté le 20-12-2006 à 15:55:49    

nORKy a écrit :

et le compilo ne te ponds pas une erreur du style
"[...] without a cast" ??


Pourquoi un compilateur C ferait-il ça ? En C, la conversion T* <-> void* est implicite dans les 2 sens.

 

Evidemment, si ce n'est pas un compilateur C, c'est un autre problème...

 

http://mapage.noos.fr/emdel/notes.htm#malloc


Message édité par Emmanuel Delahaye le 20-12-2006 à 15:56:46

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed