[C] Problème de realloc d'une table des symboles

Bonjour, j’ai un petit problème lors d’une gestion d’une table des symboles dynamique.

J’initialise une table à N valeurs et si on veut introduire une valeur supplémentaire, on fait un realloc pour agrandir la taille du tableau.

Jusque là rien de compliqué.

Ma table des symboles est une table d’une structure stokant un int, un char* et un void* et lors du realloc, les premieres valeurs de ma table sont écrasées, comme par magie. Je sais que la magie n’existe pas en info alors j’aimerai qu’on m’explique.

Je vous fournis un code d’exemple:
[cpp]#include <stdlib.h>
#include <stdio.h>

typedef struct symbole symbole;
struct symbole
{
int type;
char *s;
void *x;
};

int size=5;
int util=0;

void ajout(symbole tab, int val)
{
symbole a;
a.type=val;
a.s=(char
)malloc(sizeof(char));
a.s[0]=(char)val;

if (util>=size)
	{
	printf("Taille trop petite, realloc\n");
	realloc(tab,(size+5)*sizeof(symbole));
	size+=5;
	}

tab[util]=a;
util++;

}

void display(symbole *tab)
{
int i;
printf("[");
for (i=0;i<util;i++)printf("|%d",tab[i].type);
printf("]\n");
}

main()
{
srand(time(NULL));
int c,r;
symbole tab=(symbole)malloc(6*sizeof(symbole));
while (1)
{
r=rand()%100;
ajout (tab,r);
display(tab);
usleep(500000);
}
}[/cpp]

Et ce programme me donne cette execution:
[fixed]
[|47]
[|47|73]
[|47|73|39]
[|47|73|39|10]
[|47|73|39|10|31]
Taille trop petite, realloc
[|1075137020|73|39|10|31|45] <-là la valeur 47 a été remplacée par 1075…
[|1075137090|65|39|10|31|45|66]
[|1075137090|17|39|1075137020|31|45|48|15]
[|1075137090|17|39|1075137020|1075137020|45|32|15|36]
[|1075137090|17|39|1075137020|1075137073|17|16|15|36|49]
Taille trop petite, realloc
[|0|17|39|1075137020|1075137073|17|16|15|36|49|18]
[/fixed]

Merci

Houla, ca fait longtemps que j’ai pas fait c (je me suis mis au c#) et je suis trés fatiqué là, mais bon :

A) void ajout(symbole *tab, int val)

  • Tu reallou tab, faut passer **tab

B) Symbole a; … tab[util]=a;
Tu fait pointer un element de ton tableau sur un classe locale qui va etre détruite en sortie de fonction. C’est mal :slight_smile:

Non ça c’est bon c’est une structure. Elle va etre copié comme un type primitif. Il n’ya pas de pointeur sur pile.

pour A) je plussoie il faut utiliser une double indirection pour modifier par effet de bord le pointeur sur le tableau

petit plus si tu compte gerer de grosse table de symbole. il vait mieux augmenter la taille du tableau de maniere exponentielle et pas lineaire. Au pire la moitié du tableau n’est pas utilisé (1/4 en moyenne) mais tu gagne beaucoup en efficacité.

Pourquoi est ce que tu utilise un pointeur sur un caractere? Ce ne serait pas mieux d’utiliser directement un char? ça prend mons de place en memoire et ça fait une allocation de moins. Le seul avantage d’utiliser un pointeur serait dans le cas ou plusieurs objets utiliserait le meme caractere mais je suppose que c’est pas le cas ici.

Je vous remercie de vos réponses, guitoo pour la taille exponentielle c’est une bonne idée mais je prefere que le modèle linéaire fonctionne déja !!

Le pointeur sur caractere (char*) sert a stoker le nom de la variable que l’utilisateur a donné (dont on ne sait pas la taille)

En effet quand je supprime le char * et que je met un char à la place no problem. L’inconvénient est que je ne peux stoker qu’un seul caractere pour un nom de variable.

Par contre l’idée de la double indirection ne m’inspire pas trop… vous pouvez expliquer?

ok j’avais cru que tu ne stockais toujours qu’un seul charactere.

quand tu fait un realloc il est fortement possible que le systeme ne puisse pas rallonger le tableau a l’endroit ou il est, alors il en creer un ailleur. Dans ce cas ton nouveau tableau est positionnée a l’adresse retournée par realloc. Pour faire remonter l’information de la position du tableau tu as le choix de la retourner ou de la modifier par effet de bord.

D’accord mais s’il crée un tableau ailleurs, il ne recopie pas les premiers éléments??? Comment ça se fait les valeurs éronnées?

Et l’effet de bord ça consiste en quoi?

pour le fonctionnement de reaaloc regarde la http://www.opengroup.org/onlinepubs/007908799/xsh/realloc.html

Pour l’effet de bord ça consiste a modifié un parametre.

pour pouvoir modifier l’adresse du tableau tu doit donner un pointeur sur une case memoire qui contient l’adresse du premier element du tableau.