Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2818 connectés 

  FORUM HardWare.fr
  Programmation
  C

  erreur avec des char*

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

erreur avec des char*

n°1492246
Amonchakai
Posté le 16-12-2006 à 19:41:27  profilanswer
 

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
mood
Publicité
Posté le 16-12-2006 à 19:41:27  profilanswer
 

n°1492247
_darkalt3_
Proctopathe
Posté le 16-12-2006 à 19:42:56  profilanswer
 

Tu cast pas le retour de malloc ?

n°1492249
Amonchakai
Posté le 16-12-2006 à 19:46:12  profilanswer
 

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
n°1492275
Trap D
Posté le 16-12-2006 à 22:35:02  profilanswer
 

_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
n°1492326
Amonchakai
Posté le 17-12-2006 à 09:53:46  profilanswer
 

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 :)

n°1492329
Trap D
Posté le 17-12-2006 à 10:05:07  profilanswer
 

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.

n°1492330
Amonchakai
Posté le 17-12-2006 à 10:19:06  profilanswer
 

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

n°1492333
Emmanuel D​elahaye
C is a sharp tool
Posté le 17-12-2006 à 11:03:26  profilanswer
 

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/
n°1492336
Amonchakai
Posté le 17-12-2006 à 11:41:13  profilanswer
 

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 :)

n°1492337
Emmanuel D​elahaye
C is a sharp tool
Posté le 17-12-2006 à 12:05:06  profilanswer
 

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/
mood
Publicité
Posté le 17-12-2006 à 12:05:06  profilanswer
 

n°1492343
Amonchakai
Posté le 17-12-2006 à 12:37:28  profilanswer
 

ok, j'ai compris  
 
Merci :)

n°1492474
jesus_chri​st
votre nouveau dieu
Posté le 17-12-2006 à 22:28:03  profilanswer
 

_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.

n°1494172
nORKy
Grmmph...
Posté le 20-12-2006 à 13:50:39  profilanswer
 

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" ??
 

n°1494352
Emmanuel D​elahaye
C is a sharp tool
Posté le 20-12-2006 à 15:55:49  profilanswer
 

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/

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  erreur avec des char*

 

Sujets relatifs
Erreur d'executionErreur header(sprintf("Location: %s", $deleteGoTo));
Erreur AJAX, besoin de vous pour tester ![RESOLU]Erreur SQL : ORA-01008: Toutes les variables ne sont pas liées
convertir std::string en char*[VBA - Excel] - RESOLU - Erreur de focus sur fonction "simple"
PB:Erreur 3061 VBAProblème de débutant: erreur dès le debut "aucune action ne peut...
Erreur 403 Depuis sitemap Google [ Réglé ]Erreur javascript aléatoire
Plus de sujets relatifs à : erreur avec des char*


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR