[C] problème avec la fonction realloc()
Résolu
iunity
Messages postés
74
Date d'inscription
Statut
Membre
Dernière intervention
-
iunity Messages postés 74 Date d'inscription Statut Membre Dernière intervention -
iunity Messages postés 74 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
J'ai un problème avec la fonction realloc() en C. J'aimerais bien savoir comment elle fonctionne exactement. En fait j'aimerais bien pouvoir modifier la taille d'un tableau dynamique contenant des pointeurs vers des structures.
Si je fais
J'aurais donc bien aimé savoir ce qui ne vas pas dans ma manière d'agrandir mon tableau.
Merci d'avance.
J'ai un problème avec la fonction realloc() en C. J'aimerais bien savoir comment elle fonctionne exactement. En fait j'aimerais bien pouvoir modifier la taille d'un tableau dynamique contenant des pointeurs vers des structures.
Si je fais
*Tout->Objets=malloc(sizeof(Objet));pour créer le tableau, ça marche. Par contre si je veux l'agrandir et que je fais
*Tout->Objets=realloc(*Tout->Objets, sizeof(*Tout->Objets)+sizeof(Objet));ça ne marche plus. Ça compile bien, mais lorsque je lance le programme j'ai une grosse quantité de messages d'erreurs, du genre :
*** glibc detected *** ./test: realloc(): invalid pointer: 0xbf85a730 *** ======= Backtrace: ========= /lib/tls/i686/cmov/libc.so.6(realloc+0x39c)[0xb7c099ec] ./test[0x8048e23] ./test[0x804a3a0] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7bb0450] ./test[0x8048d51] ======= Memory map: ======== 08048000-0804b000 r-xp 00000000 08:03 10220 /home/simon/Bureau/test2/test 0804b000-0804c000 rw-p 00002000 08:03 10220 /home/simon/Bureau/test2/test 0804c000-080a9000 rw-p 0804c000 00:00 0 [heap] b75e2000-b7609000 rw-p b75e2000 00:00 0 b763b000-b767b000 rw-p b763b000 00:00 0 b767b000-b7683000 r-xp 00000000 08:02 8453 /usr/lib/libXcursor.so.1.0.2 b7683000-b7684000 rw-p 00007000 08:02 8453 /usr/lib/libXcursor.so.1.0.2 b7693000-b76d2000 r--p 00000000 08:02 104132 /usr/lib/locale/fr_FR.utf8/LC_CTYPE [...]
J'aurais donc bien aimé savoir ce qui ne vas pas dans ma manière d'agrandir mon tableau.
Merci d'avance.
11 réponses
J'ai fais ce que tu m'as dit, et maintenant j'ai un problème à la compilation. J'ai des warnings aux lignes
J'ai le message :
Et à l'exécution j'ai une erreur de segmentation.
ChargeObjet("./test.obj", &Monde, &Objet);et
ChargeObjet("./test2.obj", &Monde, &Objet2);
J'ai le message :
test.c: Dans la fonction «main» : test.c:277: attention : passing argument 3 of «ChargeObjet» from incompatible pointer type test.c:280: attention : passing argument 3 of «ChargeObjet» from incompatible pointer type
Et à l'exécution j'ai une erreur de segmentation.
Bonjour
Objets est-il un pointeur, ou un pointeur sur un pointeur ?
D'après ta première ligne, c'est un pointeur sur un pointeur, puisque tu alloues par *Tout->Objets=malloc(sizeof(Objet)); et non pas simplement Tout->Objets=malloc(sizeof(Objet));
Dans ce cas, *Tout->Objets est un pointeur, et sizeof (*Tout->Objets) c'est la taille du pointeur , pas de la zone pointée. Donc sizeof(*Tout->Objets)+sizeof(Objet)); ça ne veut pas dire grand chose.
Je crois (pas sûr) que le seul moyen est de mémoriser dans une autre variable la taille déjà allouée, et de la mettre à jour à chaque realloc (et free)
Objets est-il un pointeur, ou un pointeur sur un pointeur ?
D'après ta première ligne, c'est un pointeur sur un pointeur, puisque tu alloues par *Tout->Objets=malloc(sizeof(Objet)); et non pas simplement Tout->Objets=malloc(sizeof(Objet));
Dans ce cas, *Tout->Objets est un pointeur, et sizeof (*Tout->Objets) c'est la taille du pointeur , pas de la zone pointée. Donc sizeof(*Tout->Objets)+sizeof(Objet)); ça ne veut pas dire grand chose.
Je crois (pas sûr) que le seul moyen est de mémoriser dans une autre variable la taille déjà allouée, et de la mettre à jour à chaque realloc (et free)
En fait ça se structure comme ça :
*Objets[] est un tableau de pointeurs vers la structure Objet. A chaque fois que j'ajoute une valeur dans Objets[], j'exécute le code suivant :
Le code se trouve dans une fonction, et comme la structure Objet contient des gros éléments, j'ai préféré utiliser les pointeurs pour éviter de tout passer en paramètres.
La création du premier objet se passe bien, mais au deuxième ça plante.
J'ai essayé de mémoriser la taille déjà allouée, mais ça n'a pas marché. J'ai même essayer de mettre la taille en dur dans le programme :
et de ne charger que deux objets, mais ça ne marche toujours pas.
struct Tout { int NbObjets; struct Objet *Objets[]; }; struct Objet { [...] };
*Objets[] est un tableau de pointeurs vers la structure Objet. A chaque fois que j'ajoute une valeur dans Objets[], j'exécute le code suivant :
if(Monde->NbObjets==0) { *Monde->Objets=malloc(sizeof(Objet)); } else { *Monde->Objets=realloc(*Monde->Objets, taille+sizeof(Objet)); }
Le code se trouve dans une fonction, et comme la structure Objet contient des gros éléments, j'ai préféré utiliser les pointeurs pour éviter de tout passer en paramètres.
La création du premier objet se passe bien, mais au deuxième ça plante.
J'ai essayé de mémoriser la taille déjà allouée, mais ça n'a pas marché. J'ai même essayer de mettre la taille en dur dans le programme :
if(Monde->NbObjets==0) { *Monde->Objets=malloc(4); } else { *Monde->Objets=realloc(*Monde->Objets, 8); }
et de ne charger que deux objets, mais ça ne marche toujours pas.
Comment Monde est-il déclaré et initialisé ?
Pourquoi as-tu défini Objets comme un tableau de pointeurs ? Si tu agrandis la zone allouée à chaque fois au lieu d'allouer une nouvelle zone, tu n'as pas besoin d'un tableau et du devrais écrire Monde->Objets = malloc ou realloc
Pourquoi as-tu défini Objets comme un tableau de pointeurs ? Si tu agrandis la zone allouée à chaque fois au lieu d'allouer une nouvelle zone, tu n'as pas besoin d'un tableau et du devrais écrire Monde->Objets = malloc ou realloc
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Tout d'abord je viens de remarquer une erreur dans le code précédent. J'ai décidé de renommer la variable Tout en Monde car je ne la trouvait pas assez parlante. La première structure s'appelle désormais Monde (pas comme je l'ai écrit).
Sinon, pour être plus clair, mon code ressemble à ça :
Objets est un tableau de pointeurs car au final la structure Objet contiendra aussi un tableau dynamique, et il me semble que c'est le seul moyen de faire.
Je précise aussi que j'ai déjà essayé mon programme avec un tableau statique, et qu'il marche bien (mais je dois allouer de gros tableaux pour parfois pas grand chose).
Dernière précision : normalement ça n'a pas d'importance, mais je code sous Linux.
Sinon, pour être plus clair, mon code ressemble à ça :
struct Objet { int var1, var2, var3[...] }; struct Monde { int NbObjets; struct Objet *Objets[]; }; void ChargeObjet(char *Chemin, struct Monde *Monde, struct Objet *Objet) { if(Monde->NbObjets==0) *Monde->Objets=malloc(sizeof(Objet)); else *Monde->Objets=realloc(*Monde->Objets, sizeof(*Monde->Objets)+sizeof(Objet)); Objet->var1=42; [...] Monde->Objets[Monde->NbObjets]=Objet; Monde->NbObjets++; } main() { struct Monde Monde; Monde.NbObjets=0; struct Objet Objet; ChargeObjet("./test.obj", &Monde, &Objet); struct Objet Objet2; ChargeObjet("./test2.obj", &Monde, &Objet2); [...] }
Objets est un tableau de pointeurs car au final la structure Objet contiendra aussi un tableau dynamique, et il me semble que c'est le seul moyen de faire.
Je précise aussi que j'ai déjà essayé mon programme avec un tableau statique, et qu'il marche bien (mais je dois allouer de gros tableaux pour parfois pas grand chose).
Dernière précision : normalement ça n'a pas d'importance, mais je code sous Linux.
En fait, tu n'alloues qu'un pointeur à chaque fois, pas une structure Object ! Tes structures sont statiques.
Tu devrais donc déclarer struct Objet **Objets;
et à chaque malloc / realloc allouer une taille de sizeof( struct Object *)
Tu devrais donc déclarer struct Objet **Objets;
et à chaque malloc / realloc allouer une taille de sizeof( struct Object *)
*Monde->Objets=malloc(sizeof(struct Object *)); ou *Monde->Objets=realloc(*Monde->Objets, (Monde->NbObjets+1) * sizeof(struct Object *));
as tu pensé à allouer Monde->Objets ? il faut que tu lui dise sur combien de tableaux tu comptes le faire pointé.
J'aurai écrit
Monde->Objets=malloc(sizeof(struct Object *));
ou
Monde->Objets=realloc(*Monde->Objets, (Monde->NbObjets+1) * sizeof(struct Object *));
J'aurai écrit
Monde->Objets=malloc(sizeof(struct Object *));
ou
Monde->Objets=realloc(*Monde->Objets, (Monde->NbObjets+1) * sizeof(struct Object *));
S'il te plaît, ne fais pas de modifications parce que je te le dis, mais parce que tu comprends pourquoi il faut les faire.
Tu as dû modifier autre chose par rapport au code que tu donnes dans le message 4. Dans ce message, le 3ème paramètre est struct Objet *Objet et tu passes bien à l'appel l'adresse d'une struc Objet. On ne peut pas faire plus compatible
Peut-être as-tu mal compris la modif que je te demandais, qui concerne la définition du champ Objets dans la structure Tout ?
Tu as dû modifier autre chose par rapport au code que tu donnes dans le message 4. Dans ce message, le 3ème paramètre est struct Objet *Objet et tu passes bien à l'appel l'adresse d'une struc Objet. On ne peut pas faire plus compatible
Peut-être as-tu mal compris la modif que je te demandais, qui concerne la définition du champ Objets dans la structure Tout ?
Effectivement j'avais mal compris ce que tu avais dit. Maintenant ça a l'air de marcher. Mais il reste encore un problème, à la ligne
qui provoque un warning a la compilation et une grosse erreur à l'exécution.
Monde->Objets[Monde->NbObjets]=Objet;
qui provoque un warning a la compilation et une grosse erreur à l'exécution.