[C] problème avec la fonction realloc()

Résolu/Fermé
iunity Messages postés 75 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 16 mai 2013 - 24 sept. 2008 à 13:53
iunity Messages postés 75 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 16 mai 2013 - 24 sept. 2008 à 21:31
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
*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

iunity Messages postés 75 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 16 mai 2013 9
24 sept. 2008 à 16:10
J'ai fais ce que tu m'as dit, et maintenant j'ai un problème à la compilation. J'ai des warnings aux lignes
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.
2
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)
0
iunity Messages postés 75 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 16 mai 2013 9
24 sept. 2008 à 14:29
En fait ça se structure comme ça :
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.
0
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
iunity Messages postés 75 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 16 mai 2013 9
24 sept. 2008 à 15:27
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 :
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.
0
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 *)
 *Monde->Objets=malloc(sizeof(struct Object *));
ou
*Monde->Objets=realloc(*Monde->Objets, (Monde->NbObjets+1) * sizeof(struct Object *));
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
24 sept. 2008 à 16:33
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 *));
0
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 ?
0
iunity Messages postés 75 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 16 mai 2013 9
24 sept. 2008 à 17:43
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
Monde->Objets[Monde->NbObjets]=Objet;

qui provoque un warning a la compilation et une grosse erreur à l'exécution.
0
Je n'ai pas le temps de vérifier. Il me semble que quelque chose comme
(Monde->Objets)[Monde->NbObjets]=Objet;

serait préférable
0
iunity Messages postés 75 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 16 mai 2013 9
24 sept. 2008 à 21:31
Ta ligne ne marche pas, mais j'ai utilisé
(*Monde->Objets)[Monde->NbObjets]=Objet;
et là ça marche très bien. Je marque donc le sujet comme résolu.

Je te remercie beaucoup pour ton aide.
0