Rechercher : dans
Par :

[C]probleme d'adresse memoire

Dernière réponse le 26 fév 2008 à 04:09:49 Tisiph0n3, le 17 fév 2008 à 18:28:07 
 Signaler ce message aux modérateurs

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

Meilleures réponses pour « [C]probleme d'adresse memoire » dans :
L'adresse mémoire ne peut pas être 'Read' ou 'Written' Voir L'adresse mémoire ne peut pas être 'Read' ou 'Written' Vérifier le fonctionnement des barrettes mémoire Vérifier la présence de malwares et le cas échéant, les éradiquer Vérifier la configuration de Windows Nettoyer le disque dur Réparer...
Adresse IP VoirSommaire Qu'est-ce qu'une adresse IP Déchiffrement d'une adresse IP Adresses particulières Les classes de réseaux (obsolète) Classe A Classe B Classe C Attribution des adresses IP Adresses IP réservées Masques de sous-réseau Interet...
Langage C - Les types de données VoirLes types de données Les données manipulées en langage C sont typées, c'est-à-dire que pour chaque donnée que l'on utilise (dans les variables par exemple) il faut préciser le type de donnée, ce qui permet de connaître l'occupation mémoire (le...
Segmentation de la mémoire en assembleur VoirQu'est-ce que la segmentation de la mémoire ? En assembleur, on appelle segment de mémoire le mécanisme de base de la gestion des adresses pour des processeurs de type 80x86. Les instructions sont stockées dans le registre IP. Il s'agit d'adresses...

1

fiddy, le 17 fév 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

Tisiph0n3, le 17 fév 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

fiddy, le 17 fév 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

Tisiph0n3, le 17 fév 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

fiddy, le 17 fév 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

Tisiph0n3, le 17 fév 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

Mahmah, le 17 fév 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

Tisiph0n3, le 17 fév 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

Mahmah, le 17 fév 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

Tisiph0n3, le 17 fév 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

Mahmah, le 17 fév 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

fiddy, le 17 fév 2008 à 19:59:33
  • +2

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

Tisiph0n3, le 17 fév 2008 à 20:30:37

Arf ça ne change rien merci quand meme

Répondre à Tisiph0n3

13

Mahmah, le 17 fév 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

fiddy, le 17 fév 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

Mahmah, le 17 fév 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

fiddy, le 17 fév 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

Mahmah, le 17 fév 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

Tisiph0n3, le 17 fév 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

Mahmah, le 17 fév 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

Tisiph0n3, le 17 fév 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

fiddy, le 17 fév 2008 à 20:54:46

Petite question : Pourquoi avoir mis str en static char ?
Google is your friend

Répondre à fiddy

24

Tisiph0n3, le 17 fév 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

Mahmah, le 17 fév 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

Tisiph0n3, le 17 fév 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

Tisiph0n3, le 17 fév 2008 à 23:49:58

En fait l'adresse est tout de meme éffacée -_-'

Répondre à Tisiph0n3

27

Tisiph0n3, le 18 fév 2008 à 15:09:01

Up! :)

Répondre à Tisiph0n3

28

Mahmah, le 19 fév 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

Tisiph0n3, le 20 fév 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

Tisiph0n3, le 20 fév 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

 Keybee, le 26 fév 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
Collection CommentÇaMarche.net