[C]probleme d'adresse memoire

Résolu/Fermé
Tisiph0n3 - 17 févr. 2008 à 18:28
 Keybee - 26 févr. 2008 à 04:09
Bonjour,
actuellement je code un minishell, le probleme c'est que des fois ça segfault des fois non, ça a l'air d'etre au ptit bonheur la chance.
Je lis sur l'entrée standard, une fois la lecture effectuée je "colle" ce que j'ai récupéré a la suite de la chaine que je renverrai quand il n'y aura plus rien a lire sur l'entrée standard, pour ça j'utilise my_strndup, c'est comme strncat sauf que là ya un malloc integré.
Le probleme étant que je rentre des trucs au pif =>ça marche
Je rentre des trucs au pif encore une fois=> ça marche pas
et pas necessairement dans cet ordre
Donc gdb et là c'est le drame:
Program received signal SIGSEGV, Segmentation fault.
0x08048a29 in my_strlen (str=0x64 <Address 0x64 out of bounds>) at my_strlen.c:8
8 while (str[i] != '\0')
alors apparement l'adresse memoire de la chaine dont je cherche a recuperer la longueur cad la chaine finale a été modifiée par je ne sais quel miracle, a la place une valeur arbitraire, donc evidemment => core dump.
J'ai lu que c'était un stack overflow, alors si on pouvait me dire comment l'eviter ça serait vraiment sympa parce que là je pedale dans lvide depuis trop longtemps, voila si vous voulez un bout de sources ya qu'a demander.
merci d'avance ^^
A voir également:

13 réponses

fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
17 févr. 2008 à 19:59
Ah, je comprends mieux ce que tu veux. :)

char *my_strndup(char *str1, char *str2, int n)
{
  int   i;
  int   i2;

  i =strlen(str1);
  char *result = (char*)malloc((i+n+1)*sizeof(char));

  i=0;
  while(i<strlen(str1))
    result[i]=str1[i++];


  i=0;
  while(i<n)
    result[strlen(str1)+i]=str2[i++];

  result[strlen(str1)+n]='\0';

  return (result);
}


J'espère que c'est ce que tu attendais.
2
arf ça ne change rien merci quand meme
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
17 févr. 2008 à 18:35
Salut,

Pourrais-tu mettre ton code ici, et un exemple de ce que tu as mis qui a fait bugguer le programme.
Cordialement
0
">sdfsjdfkjdkjdkjfd dkjfdkjkjdkjdkjd lslqlmqslmslmlmqslm"
Ce genre d'entrée fout generalement la merde:
char    *my_strndup(char *str1, char *str2, int n)
{
  int   i;
  int   i2;

  i = my_strlen(str1);
  str1 = malloc(i + ((n + 1) * sizeof(*str1)));
  i2 = 0;
  while (n > i2)
    {
      str1[i] = str2[i2];
      i++;
      i2++;
    }
  str1[i] = '\0';
  return (str1);
}

char            *get_next_line(const int fd)
{
  int           reading;
  int           i;
  char          buf[BUFF];
  static char   *str;

  reading = BUFF;
  i = 0;
  str = 0;
  while (reading == BUFF)
    {
      reading = read(fd, buf, BUFF);
      while ((buf[i] != '\n') && (buf[i + 1] != '\0'))
        {
          i++;
        }
      str = my_strndup(str, buf, i);
    }
  free(str);
  return (str);
}

Et voila là où ça merde, j'ai mis la fonction qui lit sur l'entrée standard et celle qui recolle les morceaux
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
17 févr. 2008 à 18:57
Dans my_strdump, pourquoi tu calcules my_strlen(strl1) pour refaire un malloc dessus ? Si tu utilises strlen sur une chaine, c'est qu'elle est déjà allouée, sinon il ne faut pas l'utiliser. Peut-être que tu voulais écrire i=my_strlen(strl2); Non ?
0
Il faut bien que je connaisse la longueur de la premiere chaine de caractère celle a laquelle je vais coller la deuxieme pour pouvoir malloc la chaine de destination de maniere dynamique, et vu que au tout premier appel str1 pointe vers un espace memoire que j'ai initialisé a 0 (cf get_next_line) je vois pas trop le probleme en fait
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842 > Tisiph0n3
17 févr. 2008 à 19:15
Ce que je veux dire, c'est que si tu utilises strlen, c'est que le pointeur a déjà été alloué. Or, toi, tu réutilises malloc. Soit tu souhaites redéfinir l'allocation, donc tu utilises realloc. Mais, dis nous plutôt ce qu'est censé faire précisément ta fonction. Tes arguments sont utilisés comment : strl1 = source et strl2 = destination ou le contraire ?
0
Tisiph0n3 > fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022
17 févr. 2008 à 19:21
str1 = destination str2 = source
par exemple:
my_strndup("salut", "toto", 2);=>"salutto"
Mais tu sais avant je malloquais str avant de le passer en premier paramètre a strncat qui fait la mm chose sans le malloc ça merdait pareil
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
17 févr. 2008 à 19:02
Bonjour,

Moi je le prends le pari que my_strndup s'appelle en fait my_strncat...
La fonction strndup ne prend que deux paramètres elle, par contre strncat ne ferait pas d'allocation...

Quel est le but exacte de ta fonction ? Là on dirait un mix des deux.

Fiddy++; Il est louche le malloc...

M.

PS:
Faudra appeler le plombier, y a des fuites ^^"
0
euh si tu regardes bien après l'appel a strndup dans get_next_line str pointe vers une chaine malloquée je libère str a la fin de get_next_line ;)
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125 > Tisiph0n3
17 févr. 2008 à 19:29
Oui, oui, mais ta chaîne est allouée X fois avec X = Taille total du message / BUFF, et elle n'est déallouée qu'une fois à la fin.

Autre chose, dans my_strndup, lors du malloc tu obtiens une nouvelle zone mémoire qui ne contient pas le début de la chaîne str1 mais des valeurs indéfinies. il faut aussi recopier le début de str1 (que d'ailleurs tu as perdu car tu n'as plus de pointeur dessus pour récupérer tes données et que tu n'as pas déalloué) Comme disait Fiddy, realloc serait mieux adapté.

M.
0
Tisiph0n3 > Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010
17 févr. 2008 à 19:38
Bon comme t'es pas convaincu je te file un cc d'un rapport de fin d'execution avec valgrind:
==2546== malloc/free: in use at exit: 0 bytes in 0 blocks.
==2546== malloc/free: 5 allocs, 5 frees, 65 bytes allocated.
==2546== For a detailed leak analysis, rerun with: --leak-check=yes
==2546== For counts of detected errors, rerun with: -v

je pense que là ya pas photo ^^
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125 > Tisiph0n3
17 févr. 2008 à 20:01
En prenant BUFF = 2, tu saisis "abcde", ta boucle principale fait deux tours, tu fais deux malloc via my_strndup, tu ne fais qu'un free.
Pour moi il y a photo, qu'en penses-tu Fiddy s'il te plait ?

M.
0

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

Posez votre question
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
17 févr. 2008 à 20:12
Fiddy rocks ;-)

3 petits warnings tout de même (oui, je sais je suis maniaque ^^)

warning : '=' : conversion from 'size_t' to 'int', possible loss of data
pour le i = strlen

warning : '<' : signed/unsigned mismatch
pour le while(i<strlen(str1))

warning : 'i2' : unreferenced local variable
Ah...

M.

Mais ça fuit toujours. Ah oui, je suis buté aussi, confirmes-tu Fiddy ? (Juste pour la fuite hein ;-))
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
17 févr. 2008 à 20:24
Oui, ça m'apprendra à le faire sans compilateur lol.

Sinon, je pense pas qu'il y ait de fuites dans son code. Comme il te l'a dit, on effectue bien un free sur son malloc. Et comme la variable est en static, il n'y a pas de soucis.
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125 > fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022
17 févr. 2008 à 20:31
Même si la chaîne saisie est plus grande que BUFF ?
2ème tour de boucle, 2ème malloc, non ?

Promis, après je m'avoue vaincu ! ;-)

M.
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842 > Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010
17 févr. 2008 à 20:42
Oups, mal vu une accolade lol. Oui tu as raison, il manque des free. lool. Il y a des fuites. Il n'y a pas de garbage collector en C :d.
Vaudrait mieux utiliser des realloc.
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
17 févr. 2008 à 20:34
On peut avoir le code de my_strlen s'il te plait ?

C'est quand même elle qui se fait écraser son pointeur...

M.

Yep, 2 posts d'un coup ^
0
voila :) :
int     my_strlen(char *str)
{
  int   i;

  i = 0;
  if (!str)
    return (0);
  while (str[i] != '\0')
    {
      i++;
    }
  return (i);
}
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125 > Tisiph0n3
17 févr. 2008 à 20:49
Je pense qu'il n'y a pas d'écrasement de pile à moins que tu aies plusieurs threads...

Le seul autre moyen de se retrouver avec un pointeur qui vaut 0x64 c'est d'avoir voulu prendre cet offset à partir d'un pointeur null.

M.
0
ceci dit ça vient peut etre d'une autre fonction je pensais, parce qu'en fait j'avais remarqué qu'après plusieurs appels a get_next_line je retrouvait les commandes que j'avais passées precdemment, donc au bout de 10 commandes je me retrouvait avec une chaine qui contenait toutes les commandes, vraiment bizarre, le truc que j'ai donc fais c'est que juste après avoir recuperé la ligne sur l'entrée standard et en avoir fait ce que j'avais a faire, je passe l'adresse où était stockée la ligne a une fonction chargée de malloquer l'espace a cet endroit et de le remplir de 0 c'est peut etre ça
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
17 févr. 2008 à 20:54
Petite question : Pourquoi avoir mis str en static char ?
0
car un static est initialisé a 0 lors de sa declaration automatiquement je l'ai utilisé a cause du probleme que j'ai décrit juste au dessus, a chaque appel de get_next_line la chaine renvoyée contenait egalement les chaines de retour des appels precedents, ça n'as pas reglé le probleme j'ai du faire une fonction pour vider la memoire a cet endroit, je ne l'ai pas retiré.
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
17 févr. 2008 à 21:02
Au fait... (Lalalaaa...)


free(str);
return (str);


C'est pas un peu dangereux ?



Je suis d'accord aussi pour le static, il est à justifier.


M, plombier ^^
0
bon pour eviter que le pointeur soit écrasé lorque je cherche a connaitre la longueur de str1 j'ai rajouté le mot clé const devant le premier paramètre de strlen ça a déplacé le probleme maintenant c'est un autre pointeur dans une autre fonction qui est écrasé il me cherche on dirait
0
en fait l'adresse est tout de meme éffacée -_-'
0
up! :)
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
19 févr. 2008 à 20:00
A ce niveau là, il faut un bon debuggeur ou beaucoup de chance...

Je n'ai pas de théorie sur le fait que le const sur le paramètre change quoi que ce soit à lui seul...

On a plusieurs solutions en admettant que ce soit bien un écrasement et non une allocation échouée ou oubliée.

Commence par vérifier tous les tableaux (et donc chaînes de caractères), d'abord ceux en pile, puis les dynamiques, et après les statiques, c'est plus rare mais pourquoi pas...

Cela peut également aider de sécuriser via des assertions pour se rendre compte le plus vite possible d'une erreur.

L'état du précédent patient est stabilisé ? (Plus de fuites et plus de free hâtif ?)

Bonne chasse,

M.
0
Tisiph0n3 Messages postés 21 Date d'inscription mercredi 20 février 2008 Statut Membre Dernière intervention 15 mai 2014
20 févr. 2008 à 22:32
Erf probleme resolu je liberais le pointeur trop tot -_-' quel boulet je fais des fois, merci pour votre aide ^^
0
Tisiph0n3 Messages postés 21 Date d'inscription mercredi 20 février 2008 Statut Membre Dernière intervention 15 mai 2014
20 févr. 2008 à 22:34
ps: oui le patient va bien lol c'est de lui que venait le probleme, ça fuit toujours un ptit peu mais j'ai pas le choix j'ai pas le droit d'utiliser realloc a moins de le recoder moi meme
0
pff c'est tek1 et leur minishell non vraiment voit avec autre etudiant au lieu de man google lol ^^
0