rss
Rechercher : dans
Par : Pertinence Date Nom d'utilisateur
Statut : Résolu

[C]probleme d'adresse memoire

Posté par Tisiph0n3, le dimanche 17 février 2008 à 18:28:07
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 ^^
Configuration: Linux
Firefox 2.0.0.12
Répondre à Tisiph0n3  Signaler ce message aux modérateurs Aller au dernier message

1


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
fiddy, le dimanche 17 février 2008 à 18:35:07
Salut,

Pourrais-tu mettre ton code ici, et un exemple de ce que tu as mis qui a fait bugguer le programme.
Cordialement
Google is your friend
Répondre à fiddy

2


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 18:41:56
">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
Répondre à Tisiph0n3

3


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
fiddy, le dimanche 17 février 2008 à 18:57:06
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 ?
Google is your friend
Répondre à fiddy

5


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 19:08:20
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
Répondre à Tisiph0n3

6


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
fiddy, le dimanche 17 février 2008 à 19:15:05
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 ?
Google is your friend
Répondre à fiddy

8


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 19:21:08
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
Répondre à Tisiph0n3

4


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 19:02:08
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 ^^"
Répondre à Mahmah

7


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 19:17:19
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 ;)
Répondre à Tisiph0n3

9


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 19:29:28
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.
Répondre à Mahmah

10


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 19:38:05
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 ^^
Répondre à Tisiph0n3

12


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 20:01:09
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.
Répondre à Mahmah

11


  • 2
    Ce message vous semble utile, votez !
  • Ce message ne vous semble pas utile, votez !
  • Signaler ce message aux modérateurs
fiddy, le dimanche 17 février 2008 à 19:59:33
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.
Google is your friend
Répondre à fiddy

15


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 20:30:37
arf ça ne change rien merci quand meme
Répondre à Tisiph0n3

13


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 20:12:44
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 ;-))
Répondre à Mahmah

14


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
fiddy, le dimanche 17 février 2008 à 20:24:09
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.

Google is your friend
Répondre à fiddy

16


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 20:31:16
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.
Répondre à Mahmah

20


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
fiddy, le dimanche 17 février 2008 à 20:42:26
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.

Google is your friend
Répondre à fiddy

17


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 20:34:37
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 ^
Répondre à Mahmah

19


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 20:38:24
voila :) :
int     my_strlen(char *str)
{
  int   i;

  i = 0;
  if (!str)
    return (0);
  while (str[i] != '\0')
    {
      i++;
    }
  return (i);
}
Répondre à Tisiph0n3

21


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 20:49:34
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.
Répondre à Mahmah

18


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 20:36:14
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
Répondre à Tisiph0n3

22


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
fiddy, le dimanche 17 février 2008 à 20:54:46
Petite question : Pourquoi avoir mis str en static char ?
Google is your friend
Répondre à fiddy

24


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 22:29:51
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é.
Répondre à Tisiph0n3

23


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le dimanche 17 février 2008 à 21:02:33
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 ^^
Répondre à Mahmah

25


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 23:47:05
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
Répondre à Tisiph0n3

26


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le dimanche 17 février 2008 à 23:49:58
en fait l'adresse est tout de meme éffacée -_-'
Répondre à Tisiph0n3

27


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le lundi 18 février 2008 à 15:09:01
up! :)
Répondre à Tisiph0n3

28


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Mahmah, le mardi 19 février 2008 à 20:00:09
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.
Répondre à Mahmah

29


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le mercredi 20 février 2008 à 22:32:17
Erf probleme resolu je liberais le pointeur trop tot -_-' quel boulet je fais des fois, merci pour votre aide ^^
Répondre à Tisiph0n3

30


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
Tisiph0n3, le mercredi 20 février 2008 à 22:34:27
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
Répondre à Tisiph0n3

31


  • Ce message vous semble utile, votez !
  • Signaler ce message aux modérateurs
 Keybee, le mardi 26 février 2008 à 04:09:49
pff c'est tek1 et leur minishell non vraiment voit avec autre etudiant au lieu de man google lol ^^
Répondre à Keybee