reprogrammer strdup ?

reprogrammer strdup ? - C - Programmation

Marsh Posté le 08-06-2004 à 20:06:59    

voila je sais qu'il existe une fonction qui permet de copier une chaine de caractere dans un char * sans s'occupper de l'allocation  
 
mais j'arrive plus a la retrouver cette fonction


Message édité par weed le 08-06-2004 à 23:09:45
Reply

Marsh Posté le 08-06-2004 à 20:06:59   

Reply

Marsh Posté le 08-06-2004 à 20:08:51    

strdup ?
 
La fonction qui permet de faire facilement des leaks ?


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 08-06-2004 à 20:09:43    

strdup est pas standard, bien que présente sur 2 nombreux systèmes. égalements g_strdup dans la glib
 
sinon tu l'écris strlen + malloc + memcpy et voilà

Reply

Marsh Posté le 08-06-2004 à 20:14:15    

hummm ouai c'etait cette fonction la ...
mais en fait je vais faire comme Taz a dit si c'est pas standard  
dsl pour le dérangement ;)

Reply

Marsh Posté le 08-06-2004 à 20:23:35    

poste ici si t'es pas sur de l'implémentation

Reply

Marsh Posté le 08-06-2004 à 20:29:57    

Taz a écrit :

strdup est pas standard, bien que présente sur 2 nombreux systèmes. égalements g_strdup dans la glib
 
sinon tu l'écris strlen + malloc + memcpy et voilà

Fais gaffe, tu te laisse séduire par le SMS staÿle !


---------------
Au royaume des sourds, les borgnes sont sourds.
Reply

Marsh Posté le 08-06-2004 à 20:38:10    

arf zut je me prend un segment default dans la figure :
 
 
 
 

Code :
  1. void affectation_envoi (char *entete, char *data)
  2. {
  3. char *tmp_entete;
  4. //allocation de tmp_entete
  5. if (data == NULL)
  6. {        //pour l'instant c'est 6 mots de 32 bits pour l'entete mais ca peut changer  
  7.  //avec les options et padding + 1 pour '\0'
  8.  tmp_entete = (char *) malloc (6*32+1);
  9.  tmp_entete[192]='\0';
  10. }
  11. else
  12. {
  13.  tmp_entete = malloc (strlen(data)+1);
  14.  tmp_entete[strlen(data)]='\0';
  15. }
  16.         //............
  17. //affectation de valeur dans tmp_entete
  18.         //...........
  19.         printf("\n1strlen (tmp_entete)+1 %d\n",strlen (tmp_entete)+1);
  20. free(entete);  // <=== ca bloque ici
  21. entete = malloc ( strlen (tmp_entete)+1 );
  22. strcpy (entete,tmp_entete);
  23. entete[ strlen (tmp_entete) ] = '\0';
  24. free(tmp_entete);
  25. }


 
je cromprends pas trop que je ne puisse pas fazire de free sur entete. On ne peut pas changer la valeur de "entete" mais normallement on doit pouvoir changer les valeur de ce que pointe entete, faire de l'allocation, liberer la memoire ....

Reply

Marsh Posté le 08-06-2004 à 20:40:20    

déjà, fais une fonction strdup comme on t'as dit, et fais la bien, ensuite on s'occupera du code autour

Reply

Marsh Posté le 08-06-2004 à 20:46:01    

je veux bien mais l'utilité d'une fonction c'est lorsque réutilise le bout de code plusieurs fois dans le programme or la je suis quasiment sur que je referais plus de copie de chaine de caracteres de cette facon ...
 
enfin bon je vais essayer de faire une fonction strdup

Reply

Marsh Posté le 08-06-2004 à 20:48:34    

et alors ? l'utilité, c'est de rendre ton code plus modulaire, et bien séparé les petits problèmes d'allocation de ton algorithme principal

Reply

Marsh Posté le 08-06-2004 à 20:48:34   

Reply

Marsh Posté le 08-06-2004 à 21:07:44    

Code :
  1. void mon_strdup (char *cible, char *source)
  2. {
  3. // il faut peut etre tester avant s'il cible a deja alloué de la memoire,
  4. //mais comment faire  
  5. free (cible); 
  6. cible = malloc (strlen (source) +1 );
  7. strcpy (cible,source);
  8. cible [strlen(source)] = '\0';
  9. free(source);
  10. }


 
 
 

Code :
  1. void affectation_envoi (char *entete, char *data)
  2.   { 
  3.      char *tmp_entete;
  4.    
  5.      //allocation de tmp_entete  
  6.      if (data == NULL)
  7.      {        //pour l'instant c'est 6 mots de 32 bits pour l'entete mais ca peut changer   
  8.         //avec les options et padding + 1 pour '\0'  
  9.         tmp_entete = (char *) malloc (6*32+1); 
  10.         tmp_entete[192]='\0';
  11.      }
  12.      else 
  13.      {
  14.         tmp_entete = malloc (strlen(data)+1);
  15.         tmp_entete[strlen(data)]='\0';
  16.      }
  17.    
  18.             //............  
  19.      //affectation de valeur dans tmp_entete  
  20.             //...........  
  21.    
  22.             printf("\n1strlen (tmp_entete)+1 %d\n",strlen (tmp_entete)+1);
  23.      mon_strdup (entete,tmp_entete);
  24.    
  25.   }


 
 j'ai la meme erreur, un segment default a cause du free ...

Reply

Marsh Posté le 08-06-2004 à 21:08:47    

ça marche pas, c'est codé de manière très peu efficace, ça fuit

Reply

Marsh Posté le 08-06-2004 à 21:12:30    

Code :
  1. void mon_strdup (char *cible, char *source)
  2.   {
  3.      // il faut peut etre tester avant s'il cible a deja alloué de la memoire,  
  4.      //mais comment faire   
  5.      free (cible);   //<=== je libere la memoire avant de reallouer  
  6.      cible = malloc (strlen (source) +1 ); 
  7.       //une fois allouer je coupis la source dans cible
  8.      strcpy (cible,source);
  9. //et je rajoute le code fin de retour
  10.      cible [strlen(source)] = '\0';
  11. //et je libere source car j'en ai plus besoin
  12.      free(source);
  13.   }


 
je copmprends pas trop  
il y a des fuites memoires ?
ou ca ?


Message édité par weed le 08-06-2004 à 21:13:35
Reply

Marsh Posté le 08-06-2004 à 21:13:19    

[:totoz]


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 08-06-2004 à 21:20:10    

free (cible);   Faudrait initialiser cible à NULL au tout début pour pas désallouer n'importe quoi (dangereux)
 
source a été alloué par un malloc ? Sinon, free() sera vain
 
D'après mon bouquin Borland, strcpy() copie aussi le \0 terminal, donc moins compliqué.

Reply

Marsh Posté le 08-06-2004 à 21:31:49    

oh putain ...

Reply

Marsh Posté le 08-06-2004 à 21:32:26    

Carbon_14 a écrit :

free (cible);   Faudrait initialiser cible à NULL au tout début pour pas désallouer n'importe quoi (dangereux)


bahh si justement, je pense  
ca se trouve cible pointe sur quelque chose d'alloué, il faut donc liberer ...
ou peut etre tu veut dire faire un test si cible pointe vers NULL  

Code :
  1. if (*cible == NULL) free (cible);


 
[citation]
source a été alloué par un malloc ? Sinon, free() sera vain
[/citation]
tu fais allusion au tableau, je suppose qui nous empeche de faire un free
oui dans mon cas ca sera que des pointeur avec des malloc
 

Code :
  1. D'après mon bouquin Borland, strcpy() copie aussi le \0 terminal, donc moins compliqué.


oui en effet, mais je trouve que c'est pas plus mal de le remettre au cas ou j'ai oublié de le mettre dans source  

Reply

Marsh Posté le 08-06-2004 à 21:40:29    

je rêve ...

Reply

Marsh Posté le 08-06-2004 à 22:09:37    

Quand on déclare char *cible, il peut pointer vers n'importe quoi, dont en général quelque chose qui existe déjà. Le libérer d'autorité n'est pas permis car le truc "au bout du fil" ne nous appartient pas !
Si on l'initialise à NULL, on est sûr de ne pas désallouer n'importe quoi (genre couper les jambes du compilo (en 16 bits, en 32, ça doit être plus "cloisonné" ).
On ne peut désallouer que ce qu'on a alloué, free(NULL) ne fait rien donc si *cible = NULL au début, l'opération n'est pas dangereuse. Si on redésalloue ensuite, le free() n'est plus légitime donc vaut mieux (par précaution) mettre le pointeur à NULL après free(), ça évite les drames.
 
strlen(source) en cas d'oubli. Oui, mais si y a pas de '\0' dans source, pas certain que strlen() sache mesurer la longueur, car y a pas de borne...
 
EDIT : pour free(source); ce que je voulais dire est que si on déclare
char source[32], on ne peut pas, dans le module, faire un free(source). Faut qu'il provienne d'un malloc. Vaut mieux donc laisser l'opérateur gérer sa chaîne en dehors, après usage (pour laisser l'endroit dans le même état qu'il l'a trouvé).


Message édité par Carbon_14 le 09-06-2004 à 09:49:19
Reply

Marsh Posté le 09-06-2004 à 10:44:39    

Carbon_14 a écrit :

Quand on déclare char *cible, il peut pointer vers n'importe quoi, dont en général quelque chose qui existe déjà. Le libérer d'autorité n'est pas permis car le truc "au bout du fil" ne nous appartient pas !


si on recoit cible en argument, cible doit normmallement pas pointer vers n'importe quoi je pense. L'utilisateur ne va pas mettre un pointeur, qui pointe sur quelques chose d'important, en argument de mon_strdup ( );
 

Carbon_14 a écrit :

Si on l'initialise à NULL, on est sûr de ne pas désallouer n'importe quoi (genre couper les jambes du compilo (en 16 bits, en 32, ça doit être plus "cloisonné" ).


tu as par exemple avant la fonction un pointeur *ptr qui pointe vers le premier caractère d'une chaine de caractere "hello" à l'adresse 3000.

Code :
  1. char *prt = malloc (6);
  2. ptr[5]='\0';
  3. strcpy(ptr,"hello" );
  4. ma_strdup (ptr, XXX);


et si tu mets apres dans ta fonction *cible = NULL. Cela voudra dire que cible ne pointera plus sur le bloc 3000 mets vers NULL. Comment va tu faire pour liberer les 6 blocs que tu as alloué de 3000 à 3005 ? il n'y a plus moyen de retrouver la chaine de caractere "hello"  
 
 

Carbon_14 a écrit :

On ne peut désallouer que ce qu'on a alloué, free(NULL) ne fait rien donc si *cible = NULL au début, l'opération n'est pas dangereuse. Si on redésalloue ensuite, le free() n'est plus légitime donc vaut mieux (par précaution) mettre le pointeur à NULL après free(), ça évite les drames.


 
la je suis entierement de ton avis si tu as un poiteur qui pointe sur NULL cela signifie que l'on ne lui a pas alloué de la memoire, donc un free (ptr) est inutile apres un *ptr=NULL.
 

Carbon_14 a écrit :


strlen(source) en cas d'oubli. Oui, mais si y a pas de '\0' dans source, pas certain que strlen() sache mesurer la longueur, car y a pas de borne...


si '\0' manque est bien on ne peut rien faire, meme la copie de caractere avec strcpy ne pourra fonctionner car le '\0' est le seul moyen de connaitre la longueur d'une chaine de caractère si on ne l'a connais pas d'avance. Donc je pense pas trop me tromper '\0' n'est pas une tres grande supposition.
 
 

Carbon_14 a écrit :

EDIT : pour free(source); ce que je voulais dire est que si on déclare
char source[32], on ne peut pas, dans le module, faire un free(source). Faut qu'il provienne d'un malloc. Vaut mieux donc laisser l'opérateur gérer sa chaîne en dehors, après usage (pour laisser l'endroit dans le même état qu'il l'a trouvé).


ok, je suis d'accord avec toi sur ce fait que en effet si source est un tableau en dehors de la fonction on ne peut pas desallouer. Mais cela peut s'adresser égalemment à cible qui peut etre un tableau. Et la avec cet argumentation, je suis d'accord pour ne par faire de free (source); / free(cible);
 
 
Vous me parliez de fuites memoires alors mais pointer vers un NULL et perdre son bloc memoire dans la nature, ce n'est pas de la fuite ? Est ce que je me trompe ?


Message édité par weed le 09-06-2004 à 10:50:23
Reply

Marsh Posté le 09-06-2004 à 10:56:16    

et bien pour resoudre, à ce probleme de source et de cible qui peuvent etre des tableau, j'appelle la fonction  
 
strdup_malloc (char *cible,char *source)
et cela supposera que cible et source ont été alloué avec des malloc.
 
Et dans ce cas est ce que ma fonction fonctionnera t'elle ?
 

Code :
  1. void strdup_malloc (char *cible, char *source) 
  2.     { 
  3.            
  4.          if (cible != NULL) free (cible); 
  5.          cible = malloc (strlen (source) +1 ); 
  6.    
  7.           strcpy (cible,source); 
  8.           cible [strlen(source)] = '\0'; 
  9.    
  10.      //et je libere source car j'en ai plus besoin  
  11.          free(source); 
  12. *source = NULL;
  13.     }


Message édité par weed le 09-06-2004 à 10:57:44
Reply

Marsh Posté le 09-06-2004 à 11:09:41    

non
 
deja c'est quoi l'interet de créer une cible si c'est pour détruire la source ? autant garder le meme ptr :o
 
ensuite
 
void strdup_malloc (char *cible, char *source)
cible = malloc (strlen (source) +1 );
 
est mauvais, tu travailles sur une copie du ptr
 
free(source);    
*source = NULL;
=> tu peux pas ecrire '*source =' sur un ptr pointant dans le vent
 
strcpy (cible,source);    
cible [strlen(source)] = '\0';
=> la 2eme ligne sert a rien
 
si strdup retourne un ptr vers la copie, c justement pour laisser le soin a l'utilisateur d'en faire ce qu'il en veut.
 
if (cible != NULL) free (cible);
=> et si cible pointe vers qqchose pas alloué avec malloc et cie ?


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 09-06-2004 à 11:16:42    

Pour cible, ce que je disais est que si on fait
 
char *cible;
 
strdup_malloc(cible, );
le free(cible) me donne des sueurs froides.
 
char *cible = NULL;
 
strdup_malloc(cible, );
le free(cible) ne fera rien au premier appel, fera son travail au prochain tour une fois cible alloué. Si on l'initialise à NULL, ça évite les errances (un pointeur = adresse d'une variable donc char *source contient ce que le hasard veut bien tant que pas renseigné suite à utilisation).
 
Une fois qu'on fait  
free(machin);  
quand on fait ensuite  
machin = NULL; (mémoire libérée donc pointeur devenu "vacant" mais pointe encore vers zone qui vient d'être libérée)
ça permet d'inhiber tout nouveau free() qu'on ferait dessus par erreur, ou traitement systématique à tort. Assurance anti-problème.
 
Suis amateur/autodidacte donc Cf conseils des pros du site (mais on en apprend beaucoup en lisant les réponses de ceux qui pratiquent ts les jours).
 
Up !

Reply

Marsh Posté le 09-06-2004 à 11:30:36    

oui mais la le probleme reste
 
n'oublie pas que tu travailles sur une copie du pointeur de l'appelant
si tu fais free(cible); tu vas libérer les données vers lesquelles pointe cible.
ensuite
cible = NULL; => la tu mets ta copie tu pointeur a NULL, l'original (de l'appelant) sera pas modifié, il se retrouvera donc avec un pointeur pointant dans le vent mais pas NULL


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 09-06-2004 à 14:01:02    

eh oh un gosse de 6 ans y arrivent :
 

Code :
  1. // Renvoie 0 si erreur, ou la taille de la chaine si OK
  2. // source est initialise  
  3. // dest est allouee par strdup
  4. size_t strdup( const char* source, char* dest )
  5. {
  6.   size_t r = 0;
  7.   if(source)
  8.   {
  9.      r = strlen( source );
  10.   }
  11.   if(r)
  12.   {
  13.     dest = malloc(r+1);
  14.     strcpy(dest,source);
  15.   }
  16.  
  17.   return r;
  18. }


 
bordel quoi ! :o


Message édité par Joel F le 09-06-2004 à 14:41:56
Reply

Marsh Posté le 09-06-2004 à 14:05:29    

faut pas faire malloc(r+1) ?

Reply

Marsh Posté le 09-06-2004 à 14:08:14    

bin bien :o
 
dest = malloc(r); >> tu bosses sur une copie de pointeur, jlai deja dit
r+1 oui


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 09-06-2004 à 14:41:15    

BlackGoddess a écrit :

u bosses sur une copie de pointeur, jlai deja dit


 
 
pardon ??????

Reply

Marsh Posté le 09-06-2004 à 14:47:14    

STFU :  
 

Code :
  1. char* strdup(const char* s)
  2. {
  3.   size_t len;
  4.   char *ret;
  5.   if(s)
  6.   {
  7.     len = strlen(s)+1;
  8.     ret = malloc(len);
  9.     if (ret)
  10.     {
  11.        memcpy(ret,s,len);
  12.     }
  13.     else
  14.     {
  15.        ret = NULL;
  16.     }
  17.   }
  18.   else
  19.   {
  20.      ret = NULL;
  21.   }
  22.   return ret;
  23. }


 
:o


Message édité par Joel F le 09-06-2004 à 14:49:13
Reply

Marsh Posté le 09-06-2004 à 14:54:37    

Ben, au départ ton dest pointe vers n'importe quoi à l'appel de la fonction. Puis durant le malloc, tu modifies ça valeur et le fait pointer vers ton bloc de mémoire alloué. Problème, ce dest est une copie locale à ta fonction.
 
C'est bien ça? (je suis plus trop sûr là)

Reply

Marsh Posté le 09-06-2004 à 14:56:47    

le pointeur est local, mais une copie est retournée.

Reply

Marsh Posté le 09-06-2004 à 15:34:37    

belgique a écrit :

Ben, au départ ton dest pointe vers n'importe quoi à l'appel de la fonction. Puis durant le malloc, tu modifies ça valeur et le fait pointer vers ton bloc de mémoire alloué. Problème, ce dest est une copie locale à ta fonction.
 
C'est bien ça? (je suis plus trop sûr là)


 
ca vous arrive de lire de la doc ou meme les posts du dessus o_O ?

Reply

Marsh Posté le 09-06-2004 à 15:37:34    

merci Joel

Reply

Marsh Posté le 09-06-2004 à 15:42:07    

Joel F a écrit :

ca vous arrive de lire de la doc ou meme les posts du dessus o_O ?


1) je pose une question à laquelle personne n'a répondu :(
2) je n'avais pas encore vu ton nouveau post en répondant, j'avais ouvert ça dans une tab.  

Reply

Marsh Posté le 09-06-2004 à 15:47:29    

belgique a écrit :

1) je pose une question à laquelle personne n'a répondu :(


hmm, je regarde :P
 

belgique a écrit :


2) je n'avais pas encore vu ton nouveau post en répondant, j'avais ouvert ça dans une tab.


 
Toutes mes excuse :X
 
@Taz : de rien :sol:

Reply

Marsh Posté le 10-06-2004 à 10:13:20    

salut
voila strdup les gars, marche parfaitement
tester en exam machine a l'ecole et a passer tout les test :) donc si vous avez un souci demander...
 
char    *my_strdup(char *str)
{
  char  *ret;
  int   len;
  int   i;
 
  len = my_strlen(str);
  ret = malloc(sizeof(char) * len);
  for (i = 0; i < len; i++)
    ret[i] = str[i];
  return(ret);
}

Reply

Marsh Posté le 10-06-2004 à 10:22:34    

c'est moyen ... c'est quoi ce my_strlen() ??? c'est strlen() + 1 qu'il retourne j'espère ...
Et puis il faut tester le retour du malloc au minimum ..

Reply

Marsh Posté le 10-06-2004 à 10:43:56    

c'est très moyen
manque le const
sizeof(char) == 1 par définition
manque le 0 final
utilise memcpy

Reply

Marsh Posté le 10-06-2004 à 11:15:10    

char    *my_strdup(const char *str)  
{  
  char  *ret;  
  int   len;  
  int   i;  
   
  len = strlen(str);  
  if (!(ret = malloc(len)))
    {
      perror("malloc in strdup " );
      exit(0);
    }
  for (i = 0; i < len; i++)  
    ret[i] = str[i];  
  ret[i] = 0;
  return(ret);  
}
 
et voila si vous prefere comme ca ca marche aussi tres bien, mais a la rigueur je filai ca pour aider apres le gars il modifie selon ses besoin/probleme quoi ^^, mais bon tant que ca marche et que ca retourne un resultat correct c l'essentiel.
 
my_strlen c un strlen c la meme chose, javai oublie de le changer, c la mauvaise habitude que mon ecole nous a filer de recoder les fonctions de la libc plustot que de les utiliser donc mettez strlen c la meme mais bon je suppose le gars aurais vite compris en compilant non? ;)

Reply

Marsh Posté le 10-06-2004 à 11:26:17    

vi, mais c'est len+1 pour le malloc ...
car là tu écris 0 dans un endroit que tu n'as pas alloué ...
et puis memcpy c'est plus mieux ;)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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