reprogrammer strdup ? - C - Programmation
Marsh Posté le 08-06-2004 à 20:08:51
strdup ?
La fonction qui permet de faire facilement des leaks ?
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à
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
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 |
Fais gaffe, tu te laisse séduire par le SMS staÿle !
Marsh Posté le 08-06-2004 à 20:38:10
arf zut je me prend un segment default dans la figure :
Code :
|
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 ....
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
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
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
Marsh Posté le 08-06-2004 à 21:07:44
Code :
|
Code :
|
j'ai la meme erreur, un segment default a cause du free ...
Marsh Posté le 08-06-2004 à 21:08:47
ça marche pas, c'est codé de manière très peu efficace, ça fuit
Marsh Posté le 08-06-2004 à 21:12:30
Code :
|
je copmprends pas trop
il y a des fuites memoires ?
ou ca ?
Marsh Posté le 08-06-2004 à 21:13:19
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é.
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 :
|
[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 :
|
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
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é).
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 :
|
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 : |
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 |
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 ?
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 :
|
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
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 ?
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 !
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
Marsh Posté le 09-06-2004 à 14:01:02
eh oh un gosse de 6 ans y arrivent :
Code :
|
bordel quoi !
Marsh Posté le 09-06-2004 à 14:08:14
bin bien
dest = malloc(r); >> tu bosses sur une copie de pointeur, jlai deja dit
r+1 oui
Marsh Posté le 09-06-2004 à 14:41:15
ReplyMarsh Posté le 09-06-2004 à 14:47:14
STFU :
Code :
|
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à)
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. |
ca vous arrive de lire de la doc ou meme les posts du dessus o_O ?
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.
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
belgique a écrit : |
Toutes mes excuse :X
@Taz : de rien
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);
}
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 ..
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
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?
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
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