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

Poser une question


Kevin Denis
c=malloc(9); !
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é.
Parce que tu tentes de réallouer un pointeur statique alors que tu
as déjà perdu la valeur allouée par malloc().
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
En fait, c'est un strcpy() qu'il te faut ici.
--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
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).
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).
free(c);
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
Ok, vu.
J'avais réduit le programme pour qu'il présente le problème, mais oui,
il faudrait un free à la fin.
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");
:) 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.
Ok.
C'est très clair, merci
--
Kevin
Et non :
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