GNT sans publicité, site mobile, fonctionnalitées exclusives...

Question sur realloc

Le
Kevin Denis
Bonjour,

j'ai une question sur realloc:
$ cat testrealloc.c
#include <stdio.h>
#include <stdlib.h>

int main(void){
char * c=NULL;
c=malloc(8);
if (c == NULL) return -1;
c="abcdefgh";
printf("valeur du pointeur: %d",c);
printf("valeur de c: %s",c);
c=realloc(c,16);
return 0;
}
$ gcc -Wall -o testrealloc testrealloc.c
testrealloc.c: In function 'main':
testrealloc.c:9: attention : format '%d' expects type 'int', but argument 2
has type 'char *'
$ ./testrealloc
valeur du pointeur: 134514000
valeur de c: abcdefgh
Erreur de segmentation

Ma question est: pourquoi le realloc segfaulte?
Merci
--
Kevin
Lire les 67 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 14
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
JKB
Le #23330671
Le 03 May 2011 10:06:58 GMT,
Kevin Denis
Bonjour,

j'ai une question sur realloc:
$ cat testrealloc.c
#include #include
int main(void){
char * c=NULL;
c=malloc(8);



c=malloc(9); !

if (c == NULL) return -1;
c="abcdefgh";



Euh... Je ne suis pas bien certain de ce que tu veux faire ici.
"abcdefg" est un pointeur statique. Il n'a pas besoin d'être alloué.

printf("valeur du pointeur: %drn",c);
printf("valeur de c: %srn",c);
c=realloc(c,16);
return 0;
}
$ gcc -Wall -o testrealloc testrealloc.c
testrealloc.c: In function 'main':
testrealloc.c:9: attention : format '%d' expects type 'int', but argument 2
has type 'char *'
$ ./testrealloc
valeur du pointeur: 134514000
valeur de c: abcdefgh
Erreur de segmentation

Ma question est: pourquoi le realloc segfaulte?



Parce que tu tentes de réallouer un pointeur statique alors que tu
as déjà perdu la valeur allouée par malloc().

Merci



JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
JKB
Le #23330661
Le Tue, 3 May 2011 10:16:30 +0000 (UTC),
JKB
Le 03 May 2011 10:06:58 GMT,
Kevin Denis
Bonjour,

j'ai une question sur realloc:
$ cat testrealloc.c
#include #include
int main(void){
char * c=NULL;
c=malloc(8);



c=malloc(9); !

if (c == NULL) return -1;
c="abcdefgh";



Euh... Je ne suis pas bien certain de ce que tu veux faire ici.
"abcdefg" est un pointeur statique. Il n'a pas besoin d'être alloué.



En fait, c'est un strcpy() qu'il te faut ici.

printf("valeur du pointeur: %drn",c);
printf("valeur de c: %srn",c);
c=realloc(c,16);
return 0;
}
$ gcc -Wall -o testrealloc testrealloc.c
testrealloc.c: In function 'main':
testrealloc.c:9: attention : format '%d' expects type 'int', but argument 2
has type 'char *'
$ ./testrealloc
valeur du pointeur: 134514000
valeur de c: abcdefgh
Erreur de segmentation

Ma question est: pourquoi le realloc segfaulte?



Parce que tu tentes de réallouer un pointeur statique alors que tu
as déjà perdu la valeur allouée par malloc().

Merci



JKB





--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Alexandre Bacquart
Le #23331011
On 05/03/2011 12:06 PM, Kevin Denis wrote:
Bonjour,

j'ai une question sur realloc:
$ cat testrealloc.c
#include #include
int main(void){
char * c=NULL;
c=malloc(8);
if (c == NULL) return -1;
c="abcdefgh";



Ton intention est visiblement de copier la chaîne dans la mémoire
allouée, mais ça ne fonctionne pas ainsi. Ce qu'il se passe ici, c'est
que le pointeur c va pointer sur le début de la chaîne "abcdefgh"
(statique) et non plus sur la mémoire allouée par malloc (qui du coup ne
pourra pas être libérée, ce que d'ailleurs tu ne fais pas, c'est mal).

Pour copier une chaîne, il y a :

strcpy(c, "abcdefgh"); // #include
Mais il faut s'assurer d'avoir alloué la taille nécessaire. La taille
d'une chaîne C en mémoire, c'est le nombre de caractères qu'elle
contient + le '' final (donc 9 char dans ton cas). Plus proprement,
ton test devrait être :

const char str[] = "abcdefgh";

On a défini la chaîne à priori pour déterminer la taille de son tampon
avec sizeof :

char *c = malloc(sizeof(str));

On pourrait aussi faire :

char *c = malloc(strlen(str) + 1); // 8 + 1 = 9

Mais c'est moins efficace pour des chaînes statiques, car strlen()
calcule la taille de la chaîne en la parcourant (et ne compte pas le
'' final, c'est pour cette raison que je fais + 1), mais sizeof ne
calcule rien du tout (il retourne la taille du tampon statique de la
chaîne, '' inclus). Ensuite :

strcpy(c, str);

Il est important d'allouer suffisamment pour strcpy() qui ne vérifie
rien du tout. Il copie sans relâche jusqu'à rencontrer le '' final
(qui est aussi copié). Si ça déborde -> comportement indéfini (en bref,
rien ou boum tôt ou tard, mais plus le programme grossit, plus les
chances de boum augmentent).

printf("valeur du pointeur: %drn",c);



Warning: %d c'est pour les int. Pour les pointeurs, il faut utiliser %p.

Au passage, 'n' suffit pour le retour à la ligne, pas besoin d'utiliser
'r' (en sortie de printf(), ça n'aura aucun effet notable).

printf("valeur de c: %srn",c);
c=realloc(c,16);



free(c);

return 0;
}
$ gcc -Wall -o testrealloc testrealloc.c
testrealloc.c: In function 'main':
testrealloc.c:9: attention : format '%d' expects type 'int', but argument 2
has type 'char *'
$ ./testrealloc
valeur du pointeur: 134514000
valeur de c: abcdefgh
Erreur de segmentation

Ma question est: pourquoi le realloc segfaulte?



Parce-que realloc() a besoin d'un pointeur initialisé avec malloc() et
le pointeur c n'a plus cette valeur au moment de l'appel. Elle est
perdue pour ton programme (et free(c) ne fonctionnerait pas, résultat :
fuite mémoire).


--
Alex
Kevin Denis
Le #23331001
Le 03-05-2011, Alexandre Bacquart
c="abcdefgh";



Ton intention est visiblement de copier la chaîne dans la mémoire
allouée, mais ça ne fonctionne pas ainsi. Ce qu'il se passe ici, c'est
que le pointeur c va pointer sur le début de la chaîne "abcdefgh"
(statique) et non plus sur la mémoire allouée par malloc



Ok, vu.

(qui du coup ne
pourra pas être libérée, ce que d'ailleurs tu ne fais pas, c'est mal).



J'avais réduit le programme pour qu'il présente le problème, mais oui,
il faudrait un free à la fin.

Pour copier une chaîne, il y a :

strcpy(c, "abcdefgh"); // #include
Mais il faut s'assurer d'avoir alloué la taille nécessaire. La taille
d'une chaîne C en mémoire, c'est le nombre de caractères qu'elle
contient + le '' final (donc 9 char dans ton cas). Plus proprement,
ton test devrait être :

const char str[] = "abcdefgh";

On a défini la chaîne à priori pour déterminer la taille de son tampon
avec sizeof :

char *c = malloc(sizeof(str));

On pourrait aussi faire :

char *c = malloc(strlen(str) + 1); // 8 + 1 = 9

Mais c'est moins efficace pour des chaînes statiques, car strlen()
calcule la taille de la chaîne en la parcourant (et ne compte pas le
'' final, c'est pour cette raison que je fais + 1), mais sizeof ne
calcule rien du tout (il retourne la taille du tampon statique de la
chaîne, '' inclus). Ensuite :

strcpy(c, str);



De manière bien plus rapide et sans doute moins propre, je devrais
pouvoir faire:
c=malloc(9);
strcpy(c,"abcdefgh");
c=realloc(c,17);
strcpy(c,"abcdefghabcdefgh");

Il est important d'allouer suffisamment pour strcpy() qui ne vérifie
rien du tout. Il copie sans relâche jusqu'à rencontrer le '' final
(qui est aussi copié). Si ça déborde -> comportement indéfini (en bref,
rien ou boum tôt ou tard, mais plus le programme grossit, plus les
chances de boum augmentent).



:) C'est écrit explicitement dans le man, j'ai vu. Ceci dit, j'ai testé et
j'ai aussi bien des segfault que des fonctionnements normaux.

printf("valeur du pointeur: %drn",c);



Warning: %d c'est pour les int. Pour les pointeurs, il faut utiliser %p.



Ok.

Au passage, 'n' suffit pour le retour à la ligne, pas besoin d'utiliser
'r' (en sortie de printf(), ça n'aura aucun effet notable).

printf("valeur de c: %srn",c);
c=realloc(c,16);



free(c);

return 0;
}
$ gcc -Wall -o testrealloc testrealloc.c
testrealloc.c: In function 'main':
testrealloc.c:9: attention : format '%d' expects type 'int', but argument 2
has type 'char *'
$ ./testrealloc
valeur du pointeur: 134514000
valeur de c: abcdefgh
Erreur de segmentation

Ma question est: pourquoi le realloc segfaulte?



Parce-que realloc() a besoin d'un pointeur initialisé avec malloc() et
le pointeur c n'a plus cette valeur au moment de l'appel. Elle est
perdue pour ton programme (et free(c) ne fonctionnerait pas, résultat :
fuite mémoire).



C'est très clair, merci
--
Kevin
Alexandre Bacquart
Le #23331091
On 05/03/2011 02:31 PM, Kevin Denis wrote:
Le 03-05-2011, Alexandre Bacquart
const char str[] = "abcdefgh";

On a défini la chaîne à priori pour déterminer la taille de son tampon
avec sizeof :

char *c = malloc(sizeof(str));

On pourrait aussi faire :

char *c = malloc(strlen(str) + 1); // 8 + 1 = 9

Mais c'est moins efficace pour des chaînes statiques, car strlen()
calcule la taille de la chaîne en la parcourant (et ne compte pas le
'' final, c'est pour cette raison que je fais + 1), mais sizeof ne
calcule rien du tout (il retourne la taille du tampon statique de la
chaîne, '' inclus). Ensuite :

strcpy(c, str);



De manière bien plus rapide et sans doute moins propre, je devrais
pouvoir faire:



Et non :

c=malloc(9);
strcpy(c,"abcdefgh");



const char str[] = "abcdefgh";
char *c = malloc(sizeof(str));
strcpy(c, str);

C'est strictement aussi efficace (avec un compilateur ne datant pas de
l'âge de pierre, et encore).

Faire du C efficace, c'est déjà savoir ce qui est statique (ie. connu au
moment de la compilation) et ce qui ne l'est pas. Pour sizeof, cet
opérateur ne retourne que des valeurs statiques. Si tu compares les
codes compilés (et que tu connais un peu l'assembleur), tu verras que
l'argument de malloc() sera 9 dans les deux cas (autrement dit, aucune
fonction sizeof n'est appelée).

Et pour la chaîne :

const char str[] = "abcdefgh";

Ceci définit une chaîne statique, ce qui revient au même que de passer
la chaîne littéralement à strcpy().

Ta méthode est juste plus "rapide à écrire", mais au final, le résultat
est le même. La différence, c'est que ton code sera plus difficile à
maintenir : changer la chaîne nécessite pour le programmeur de
recalculer sa taille pour changer l'argument de malloc(). C'est non
seulement ennuyeux, mais source d'erreurs. Avec ma méthode, le
programmeur change... la chaîne. C'est tout.

Résultat : c'est moins rapide à écrire, mais plus propre, plus sûr et à
terme, plus simple à maintenir.



--
Alex
Publicité
Suivre les réponses
Poster une réponse
Anonyme