Léa-Linux & amis :   LinuxFR   GCU-Squad   GNU
Probleme de realloc pour un tableau 2D
Envoyé par: ptit_riton

Bonjour à tous,

Désolé de déranger pendant les périodes de vacances de noel, mais les erreurs C ne prennent pas de vacances !

Je travaille sur un projet qui doit lire un fichier XML pour sa configuration. De ce coté là, pas de problème, mais ... je ne sais pas d'avance combien de structure du type

<client>
<id>IDENTIFIANT</id>
<ip>@IP</ip>
</client>

peuvent se trouver dans ce fichier de configuration, et je passe donc par un realloc pour gérer cela de façon dynamique.

Le gros problème, c'est que la LibC GNU n'est pas contente, elle m'insulte avec un classique "invalid next size".

Pour simplifier le code et juste résoudre le problème, j'ai écrit cela :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

typedef struct client{
	char ip[32];
	char id[128];
} client;

int main(int argc, char **argv) {

	client **test;
	client **temp;
	int i = 0;

	int orig = 2;
	int new = orig*2;

	test = (client **) malloc(sizeof(client *)*orig);
	
	for(i=0;i<orig;i++){
		test = (client *)malloc(sizeof(client));
	}

	fprintf(stdout,"Reallocation de %i vers %i :\n\n",orig,new);

	int u = 0;

	while(u++<5){

		strcpy(test[0]->ip,"TEST");

		fprintf(stdout,"TEST(0) == %s\n",test[0]->ip);

		if((temp = realloc(test,sizeof(client *)*new)) == NULL){
			fprintf(stderr,"Erreur avec le realloc : %s\n",strerror(errno));
			return(-1);
		}
		test = temp;
		
		fprintf(stdout,"REALLOC EFFECTUE :: TEST(0) == %s\n",test[0]->ip);
		
		new = orig*2;

		for(i=orig;i<new;i++){
			test = (client *)malloc(sizeof(client));
			orig = new;
		}

		strcpy(test[1]->ip,"TEST2");

	}

	fprintf(stdout,"TEST(1) == %s\n",test[1]->ip);
	fprintf(stdout,"TEST(0) == %s\n",test[0]->ip);


	i=0;

	while(*test!=NULL){
		fprintf(stdout,"%i => %s\n",++i,(*test)->ip);
		test++;
	}

	return (0);
}

Ce code ne sert vraiment à rien, ormis allouer de la mémoire, mais il met en pratique ce que je dois faire : faire une boucle de reallocation de mémoire.

J'ai en vain essayé de passer par des client*** comme j'avais pu le voir sur d'autres forum :
Exemple :

client **tableau;
client ***temp = realloc(&tableau,NEW_SIZE);
[...] // TESTS
tableau = *temp;

Je commence à être désespéré, please HELP !!

Merci d'avance et bonnes fêtes à tous

Poste le Saturday 27 December 2008 12:30:55
Répondre     Citer    
Re: Probleme de realloc pour un tableau 2D

Je n'ai pas compris quelle est la question.

D'ailleurs, on peut toujours se passer de realloc, et faire juste un malloc suivi d'une recopie.

Par ailleurs, je signale à ceux qui programment en C que la librarie gc de Boehm fournit un ramasse-miette conservateur qui permet d'éviter les free. En effet, il balaye la mémoire et la (ou les) pile(s) d'appel en marquant toutes les zones pointées, et en libérant si besoin celles qui ne le sont pas. Il y a bien évidemment des précautions à suivre, et ce ramasse-miettes n'est pas parfait, mais très utile.


----

Basile STARYNKEVITCH

Membre de l'APRIL « promouvoir et défendre le logiciel libre » - adhérez vous aussi à l'APRIL!

Projet logiciel libre: RefPerSys

Poste le Saturday 27 December 2008 12:36:48
Répondre     Citer    
Re: Probleme de realloc pour un tableau 2D
Envoyé par: ptit_riton

Merci de t'intéresser a mon problème.

Désolé de ne pas avoir été clair du premier coups.

Alors, mon problème vient du realloc, il me sort un "invalid next size" a la troisième itération de ma boucle While.

Les deux premières itérations font bien ce qu'on leur demande, mais lors du troisième passage, patatra, GlibC detected ... "invalid next size".

Ma question est donc simple,

Je dois gérer un tableau de structure (client **) et je souhaite réallouer l'espace mémoire (tout en conservant les données déjà enregistrées avant la réallocation, mais j'ai cru comprendre que realloc gérait tout cela) afin d'agrandir mon "tableau".

Voilà, merci encore
Salut

Poste le Saturday 27 December 2008 12:41:50
Répondre     Citer    
Re: Probleme de realloc pour un tableau 2D

client ***temp = realloc(&tableau,NEW_SIZE);

Cette instruction là est surement fausse. Le premier argument de realloc doit nécessairement être un pointeur obtenu par malloc ou realloc (ou bien le pointeur NULL). Ce ne peut donc pas être l'adresse d'une variable.

Mais je me répète: quelle est la question posée? Je ne comprends pas!

----

Basile STARYNKEVITCH

Membre de l'APRIL « promouvoir et défendre le logiciel libre » - adhérez vous aussi à l'APRIL!

Projet logiciel libre: RefPerSys

Poste le Saturday 27 December 2008 12:44:59
Répondre     Citer    
Re: Probleme de realloc pour un tableau 2D
Envoyé par: ptit_riton

Bon, cette fois je vais faire simple alors:

Pouvez vous me donner un exemple de boucle while (un nombre d'itération supérieur à 3) contenant une instruction de "realloc" avec une structure ?

Le code que j'ai fourni conduit systématiquement à des erreurs, pour plus de 3 itérations

merci d'avance

Poste le Saturday 27 December 2008 13:36:25
Répondre     Citer    
Re: Probleme de realloc pour un tableau 2D

Voici ton programme légèrement modifié (mais bogué):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#define dbgprintf(Fmt, ...) printf("%s:%d: " Fmt "\n", __FILE__, __LINE__, __VA_ARGS__)
typedef struct client
{
  char ip[32];
  char id[128];
} client;

int
main (int argc, char **argv)
{

  client **test;
  client **temp;
  int i = 0;

  int orig = 2;
  int new = orig * 2;

  dbgprintf ("malloc orig %d", orig);
  test = (client **) malloc (sizeof (client *) * orig);
  for (i = 0; i < orig; i++)
    {
      test[ i ] = (client *) malloc (sizeof (struct client));
    }
  dbgprintf ("Reallocation de %i vers %i :", orig, new);
  int u = 0;
  while (u++ < 5)
    {
      strcpy (test[0]->ip, "TEST");
      dbgprintf ("TEST(0) == %s", test[0]->ip);
      dbgprintf ("realloc test %p u %d orig %d new %i", (void *) test, u, orig, new);
      if ((temp = realloc (test, sizeof (client *) * new)) == NULL)
	{
	  fprintf (stderr, "Erreur avec le realloc : %s\n", strerror (errno));
	  return (-1);
	}
      test = temp;
      dbgprintf ("REALLOC EFFECTUE new %d :: TEST(0) == %s", new,
		 test[0]->ip);
      new = orig * 2;
      dbgprintf("ici new=%d", new);
      for (i = orig; i < new; i++)
	{
	  test[ i ] = (client *) malloc (sizeof (struct client));
	  orig = new;
	}
      strcpy (test[1]->ip, "TEST2");
    }
  dbgprintf ("TEST(1) == %s\n", test[1]->ip);
  dbgprintf ("TEST(0) == %s\n", test[0]->ip);
  i = 0;
  while (*test != NULL)
    {
      dbgprintf ("%i => %s\n", ++i, (*test)->ip);
      test++;
    }
  return (0);
}

à la troisième itération tu re-alloues avec new valant 4, mais la boucle ligne 46 va de 4 à 8, donc ton tableau déborde.

A mon avis, les affectations à new sont mal placées.

Et je ne comprends pas pourquoi new varie dans le corps de ta boucle.

Quels sont tes invariants de boucle?
[^]je n'arrive pas à les deviner, et j'imagine qu'ils seraient faux. Je m'attendais à quelque chose du genre "la taille de la zone p est n"[/^]

Enfin, il faut vraiment éviter de nommer une variable avec un mot clé de C++ (pour la simple raison que tu voudrais peut-être plus tard compiler ton code avec C++).

J'ai l'impression que tu n'as pas essayé de déboguer ton programme.


----

Basile STARYNKEVITCH

Membre de l'APRIL « promouvoir et défendre le logiciel libre » - adhérez vous aussi à l'APRIL!

Projet logiciel libre: RefPerSys

Poste le Saturday 27 December 2008 14:07:21
Répondre     Citer    
Re: Probleme de realloc pour un tableau 2D
Envoyé par: ptit_riton

Pfiou !!

Merci beacoup !!

Je me suis rendu compte que mon programme que j'avais réécri en deux temps trois mouvements pour essayer de simplifier les choses était complétement bogué ( comme tu me l'as fait remarqué à juste titre ), je faisais un gros n'importe quoi au milieu avec les indices.

Le voir réécrit et surtout avec tes messages de debug a fait qu'il a fonctionné en 2 secondes.

Merci encore, et désolé du dérangement, vu qu'en fait c'était entièrement ma faute (comme souvent),

Merci bien du temps que tu as pris pour me répondre

Poste le Saturday 27 December 2008 14:52:08
Répondre     Citer    

Veuillez vous authentifier auparavant pour commenter.

 

Ce forum !
Probleme de realloc pour un tableau 2D
Pour poser vos questions sur les scripts shell, le Perl, le C, etc... Attention : nous ne sommes pas des spécialistes du dev, ce forum est juste pour de petites aides ponctuelles concernant le développement et les outils de développement.

Sauf mention contraire, les documentations publiées sont sous licence Creative-Commons