Partage
  • Partager sur Facebook
  • Partager sur Twitter

probleme avec malloc/free

instructions d'une fonction exécutées dans le mauvaise ordre

Sujet résolu
    21 février 2020 à 14:21:54

    Bonjour, 

    J'écris un mini printf, et j ai un soucis que je ne comprend vraiment pas. Voici la fonction qui me pose problème 

    int					ft_conversion_p(va_list *arg, int nb, int pos, int min)
    {
    	char *s;
    	char 			*x;
    	int				taille;
    	int				a;
    
    	s = va_arg(*arg, char*);
    	a = 0;
    	if (s == NULL && nb >= 0 && min < 0)// && min == -1)
    		x = ft_strdup("0x0");
    	else if (s == NULL)
    		x = ft_strdup("0x");
    	else
    		x = itoa_base_pointeur(s);     // fonction qui recupere l'adresse du pointeur
    	taille = nb - (int)ft_strlen(x);
    	a += ft_positionstr(x, taille, pos);  // fonction qui me permet d'afficher l adresse du pointeur en appliquant des flags trouvés
    	free(x);
    	return (a);
    }

    Je ne met pas tous mon code sinon, on ne va pas s'en sortir. Ma variable x, prend en valeur 0X, 0X0 ou le resultat d'une fonction qui lui renvoi l'adresse du pointeur (itoa_base_pointeur).

    Que ce soit ft_strdup ou ma fonction itoa_base_pointeur, j'alloue de la memoire avec malloc. Je suis donc obligée de free mon x pour ne pas avoir de leaks. La ou cela pose probleme, c est que quand je ne free pas, j'obtiens le resultat voulu, lorsque je free j'obtiens une autre valeur. 

    Ici ma fonction ft_position_str s'occupe de bien positionner et d'afficher ce qui se trouve dans ma variable x.

    Par exemple lorsque j'attend la sortie  |0x123          |, ma fonction ft_position_str me donne bien cette sortie si je ne free pas, par contre si je free, elle me renvoi  |0x123eee66bf78 |.

    Ce que je n'arrive pas à comprendre, c'est pourquoi le fait de free a un impact, puisque je free après l'apel de cette fonction, et que je free bien quand la variable x n'est plus utilisée par quelconque fonction de mon programme.

    En fait j 'ai l'impression que cela modifie ma variable avant l'apel de la fonction ft_position_str, alors franchement je ne comprend vraiment pas comment cela est possible. 

    Je ne sais pas si c 'etait bien claire, mais si quelqu'un voit une raison valable au fait que la derniere instruction de ma fonction a un impact sur le les instructions precedentes, je suis preneuse. 

    Merci pour votre aide. 

    • Partager sur Facebook
    • Partager sur Twitter
      21 février 2020 à 14:58:43

      Salut,
      Pas certain de comprendre ton code. Es-tu certaine que malloc est appelé partout où tu pense?
      Car si tu fais un free sur quelque chose qui n'a pas été alloué, ça peut poser problème.
      Tu sembles passer les arguments d'une fonction à nombre variable d'arguments à une autre. Pas certain que ça marche.
      • Partager sur Facebook
      • Partager sur Twitter

      Le Tout est souvent plus grand que la somme de ses parties.

        21 février 2020 à 15:29:41

        On peut passer la va_list à une autre fonction.

        exemple de fonction standard :

        int vprintf(const char *format, va_list ap);

        Si on free une zone qui n'a pas été alloué par malloc (pour faire simple) c'est une erreur à l'éxécution.

        J'ai un doute , mais la page du man me le confirme.

        Crashes in malloc(), calloc(), realloc(), or free() are almost always related to heap corruption, such as overflowing an allocated chunk or freeing the same pointer twice.

        Le free de la ligne 18 n'a pas d'impact sur la valeur de retour calculé précédemment.
        Ton free est dans la fonction et non après cette fonction, je n'ai pas compris ce que as dis :( 



        • Partager sur Facebook
        • Partager sur Twitter
          21 février 2020 à 16:30:57

          oui je suis certaine de malloc, avec itoa_base_pointeur. Par exemple si je ne free pas et que je fais un system("leaks a.out"), il me confirme des leaks. par contre si je free et bien mon resultat n'est pas bon... Mon programme printf fonctionne sure à 100%, j ai juste un pb avec la conversion p, qui me renvoi parfois des valeurs aleatoires si je free. quand cette fonction est appelé, on lui envoi la liste pour recuperer la prochain argument à traiter, cela marche pour toute les conversion de mon printf, donc normalement cela ne devrait pas etre le soucis...

          Je n'ai pas le droit d'utiliser vprintf... Ceci dit je ne free pas quelque chose qui n'est pas malloc normalement... Le truc c'est que ça ne crash pas mais ça me renvoi seulement une valeur qui n'est pas la bonne. 

          Je suis d'accord sur le free qui n'a pas d'impact à priori... mais la etrangement si et tout le probleme est bien la. 

          Voici un exemple peut etre un peu plus concret : 

          deja voici ce que je test dans mon main (comparaison avec le vrai printf et mon printf) : 

          tmp2 = (void *)0x123;
          a = printf("%d\t\t\t\t: |%-*p|\n", 152, -16, (void *)tmp2);
          b = ft_printf("%d\t\t\t\t: |%-*p|\n", 152, -16, (void *)tmp2); 
          
          printf ("retour printf : %d, \n retour ft_printf : %d\n", a, b );

          Quand je ne free pas, j'ai le bon retour : 

          152     %-*p                    : |0x123           |
          152     %-*p                    : |0x123           |
          retour printf : 32, 
           retour ft_printf : 32

          mais quand je free, j'ai aleatoirement (j imagine que c est du à une adresse differente à chaque compilation) soit le bon retour, soit ceci : 

          152     %-*p                    : |0x123           |
          152     %-*p                    : |0x123eee66bf78  |
          retour printf : 32, 
           retour ft_printf : 32

          cela me fait ce probleme sur une vingtaine de tests differents, j'ai toujours le bon resultat quand je ne free pas et un resultat dans 80% des cas mauvais quand je free. 

          Je seche totalement sur la raison... Je pourrai tres bien ne pas free et ne pas me prendre la tete, mais je dois avoir un code qui ne leaks pas quoi qu'il arrive sino mon projet n'est pas valide... 

          Je n'ai jamais rencontré ce probleme et je ne trouve ça pas du tout logique, hormis si il y a quelque chose que je n 'ai pas saisi... 


          ps : autre possibilité, ne pas malloc avec itoa_base_pointeur... mais prtaiquement pas possible, connaissez vous une focntion pour recuperer le resultat d'un malloc dans une chaine de caractere ? ça m eviterait d'avoir à free...



          -
          Edité par marioonb 21 février 2020 à 16:37:41

          • Partager sur Facebook
          • Partager sur Twitter
            21 février 2020 à 19:05:00

            Hello,

            Et si tu montrais le code de la fonction itoa_base_pointer() ?

            • Partager sur Facebook
            • Partager sur Twitter

            On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

              21 février 2020 à 23:45:16

              J'ai trouvé !!!!!!!!!!!!! après 1 semaine de lutte acharnée lol. 

              En fait, mon free a du permettre de liberer de l'espace, et celui ci etait reutilisé, du coup cela m'affichait bien le debut de mon resultat, mais en plus la suite des resultats de mes tests precedents (comme si ce que je mettais dans mon malloc se superposait du malloc precedent) Du coup c'etait aleatoire à chaque compilation... J'ai utilisé un calloc et j'ai aussi changé ma fonction itoa_base_pointeur pour la simplifier et supprimer un malloc. Merci le debugeur VS code !!

              Si certains sont calés sur la question, je suis interessée pour des explications un peu plus technique afin que je ne refasse pas une erreur aussi pourrie que cela, et aussi chronophage. 

              Voici mes deux fonction itoa_base_pointeur (ancienne et nouvelle version). 

              ancienne fonction : 

              static char			*change_base(unsigned long adr, const char *base)
              {
              	int				i;
              	int				j;
              	char			res[9];
              	char			*resultat;
              
              	i = 8;
              	while ((adr / 16) > 0 || i > 8)
              	{
              		res[i] = base[(adr % 16)];
              		adr /= 16;
              		i--;
              	}
              	res[i] = base[(adr % 16)];
              	resultat = malloc(sizeof(char) * (9 - i + 2));
              	j = 0;
              	resultat[j] = '0';
              	resultat[j + 1] = 'x';
              	j = 0;
              	while (i < 9)
              	{
              		resultat[j + 2] = res[i];
              		i++;
              		j++;
              	}
              	return (resultat);
              }
              
              char				*itoa_base_pointeur(void *p)
              {
              	unsigned long	adr;
              	char const		*base;
              	char			*resultat;
              
              	adr = (unsigned long)p;
              	base = "0123456789abcdef";
              	resultat = change_base(adr, base);
              	return (resultat);
              }

              et la nouvelle : 

              char				*itoa_base_pointeur(void *p)
              {
              	unsigned long	adr;
              	char const		*base;
              	char			*resultat;
              	int				i;
              	int				j;
              	char			res[9];
              
              	adr = (unsigned long)p;
              	base = "0123456789abcdef";
              	i = 8;
              	while ((adr / 16) > 0)// || i > 8)
              	{
              		res[i] = base[(adr % 16)];
              		adr /= 16;
              		i--;
              	}
              	res[i] = base[(adr % 16)];
              	resultat = calloc((9 - i + 2), 1);
              	resultat[0] = '0';
              	resultat[1] = 'x';
              	j = 2;
              	while (i < 9)
              		resultat[j ++ ] = res[i++];
              	return (resultat);
              }

              Merci !!

              • Partager sur Facebook
              • Partager sur Twitter

              probleme avec malloc/free

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown