Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 20/11/2007, à 16:14

TatSou-Max

[Résolu] Programme en C: erreur de segmentation.

Bonjour à  tous,

Je fais un programme en langage C, me permettant d'implémenter sous forme de Tas, un algorithme de tri de chaà®ne de caractère.
La compilation se passe très bien mais lors de l'exécution de mon programme, il me renvoi:
Erreur de segmentation (core dumped)

Voici mes 2 fichiers:

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

#include "memoire.h"
#include "implementation_tas.h"

void
usage (char *s) {
  fprintf (stderr, "usage: %s\n", s);
  exit (EXIT_FAILURE);
}

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

 /*  if (argc < 3) */
/*     usage (argv[0]); */
  int targc = argc - 1;
  for (int i = 1; i <= argc; i++)
    insererDansTas(argv[i], targc);
  
  for (int i = 0; i <= targc; i++) {
    char *racine = supprimerDansTas();
    printf ("%s", racine);
    desallocation(targc-i);  
  }
  desallocation_t();
}

et

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

#include "memoire.h"
#include "implementation_tas.h"

static void **t = NULL;
static unsigned dernier_calculer = 0;
/* static unsigned racine = 0; */
/* static void (*compare) (void *, void*) = NULL; */

void
creer_tas (int taille) {
    t = memoire_allouer(taille +1 * sizeof(*t));
}

unsigned
filsGauche (unsigned sommet) {
  if (t[2*sommet] == NULL)
    return 0;
  else
    return (2*sommet);
}

unsigned
filsDroit (unsigned sommet) {
  if (t[2*sommet + 1] == NULL)
    return 0;
  else
    return (2*sommet + 1);
}

unsigned
pere (unsigned sommet) {
  if (sommet%2 == 0)
    return (sommet/2);
  else
    return ((sommet-1)/2);
}

void
echanger (unsigned s1, unsigned s2) {
  void *tmp =t[s1];
  t[s1] = t[s2];
  t[s2] = tmp;
}

void
insererValeur (char *s) {
  t[dernier_calculer] = s;
}

void
reorganiseTasMontant (unsigned sommet) {
  unsigned p;
  bool signal;
  p = pere(sommet);
  signal = 1;
  while ((sommet != 0) && (signal == 1)) {
    if (strcmp (t[sommet], t[p]) > 0) {
	echanger (sommet, p);
	sommet = p;
	p = pere(sommet);
      }
    else
      signal = 0;
  }
}

char *
supprimerValeur (void) {
  char *racine = t[0];
  t[0] = t[dernier_calculer];
  return racine;
}

void
reorganiserTasDes (unsigned sommet) {
  unsigned g = filsGauche(sommet);
  unsigned d = filsDroit(sommet);
  if (g != 0) {
    if (d != 0) {
      if (strcmp (t[d], t[g]) > 0)
	g = d;
    }
    if (strcmp (t[sommet], t[g]) < 0) {
      echanger (sommet, g);
      reorganiserTasDes(g);
    }
  }
}

/* bool */
/* EstFeuille (unsigned sommet) { */
/*   return (filsGauche(t, sommet) == NULL && filsDroit(t, sommet) == NULL); */
/* } */

void
insererDansTas (char *s, int taille) {
  if (t == NULL)
    creer_tas (taille);
  unsigned longueur = strlen(s);
  t[dernier_calculer] = memoire_allouer (longueur + 1 * sizeof(char));
  insererValeur(s);
  reorganiseTasMontant(dernier_calculer);
  dernier_calculer++;
}

char *
supprimerDansTas (void) {
  char *racine = supprimerValeur();
  reorganiserTasDes(0);
  dernier_calculer--;
  return racine;
}

void
desallocation (unsigned indice) {
  memoire_liberer(t[indice]);
}

void 
desallocation_t (void) {
  memoire_liberer(t);
}

Voici le retour de la commande valgrind ./trier

==13586== Memcheck, a memory error detector.
==13586== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==13586== Using LibVEX rev 1732, a library for dynamic binary translation.
==13586== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==13586== Using valgrind-3.2.3-Debian, a dynamic binary instrumentation framework.
==13586== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==13586== For more details, rerun with: -v
==13586== 
==13586== Invalid read of size 1
==13586==    at 0x804887B: insererDansTas (implementation_tas.c:102)
==13586==    by 0x8048547: main (trier.c:20)
==13586==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==13586== 
==13586== Process terminating with default action of signal 11 (SIGSEGV)
==13586==  Access not within mapped region at address 0x0
==13586==    at 0x804887B: insererDansTas (implementation_tas.c:102)
==13586==    by 0x8048547: main (trier.c:20)
==13586== 
==13586== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 1)
==13586== malloc/free: in use at exit: 4 bytes in 1 blocks.
==13586== malloc/free: 1 allocs, 0 frees, 4 bytes allocated.
==13586== For counts of detected errors, rerun with: -v
==13586== searching for pointers to 1 not-freed blocks.
==13586== checked 59,748 bytes.
==13586== 
==13586== LEAK SUMMARY:
==13586==    definitely lost: 0 bytes in 0 blocks.
==13586==      possibly lost: 0 bytes in 0 blocks.
==13586==    still reachable: 4 bytes in 1 blocks.
==13586==         suppressed: 0 bytes in 0 blocks.
==13586== Rerun with --leak-check=full to see details of leaked memory.
Erreur de segmentation (core dumped)

Et j'ai également fais tourné mon programme avec GDB.
Je pense avoir identifié un problème dans l'appel de la fonction main, avec argc = 1 dans n'importe quel cas.
Mais même en retournant mon programme dans tous les sens, je n'arrive pas corriger ce message d'erreur.

Donc si quelqu'un pouvait trouver le problème et surtout me l'expliquer, ce serait sympathique.
Merci à  tous,
cordialement.

Dernière modification par TatSou-Max (Le 21/11/2007, à 19:46)

Hors ligne

#2 Le 20/11/2007, à 17:33

qqun

Re : [Résolu] Programme en C: erreur de segmentation.

moi je dirais apremiere vue que le pb se situe dans l'allocation memoire.

dans creer_tas() ,
t = memoire_allouer(taille +1 * sizeof(*t));
me semble louche .
t = memoire_allouer( (taille +1) * sizeof(*t));  ?

#3 Le 20/11/2007, à 17:47

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

J'ai essayé mais cela ne donne rien.

Hors ligne

#4 Le 20/11/2007, à 20:45

telliam

Re : [Résolu] Programme en C: erreur de segmentation.

tu passes quoi comme parametres à  ton programme?


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#5 Le 20/11/2007, à 20:50

telliam

Re : [Résolu] Programme en C: erreur de segmentation.

tu dépasses le tableau argv

for (int i = 1; i <= argc; i++)
    insererDansTas(argv[i], targc);

met < à  la place de <=

Dernière modification par telliam (Le 20/11/2007, à 20:50)


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#6 Le 20/11/2007, à 21:47

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

voilà ce que j'attends de ce programme:

je rentre

./trier agj byuv  ecbfh dfhf

et le programme m'affiche

agj byuv dfhf ecbfh fkmp

J'ai modifié mon code comme tu me l'as conseillé, ce qui donne maintenant:

int targc = argc - 1;
  for (int i = 1; i < argc; i++)
    insererDansTas(argv[i], targc);
  
  for (int i = 0; i < targc; i++) {
    char *racine = supprimerDansTas();
    printf ("%s", racine);
    desallocation(targc-i);  
  }
  desallocation_t();

Mais l'exécution de mon programme me renvoi alors:

*** glibc detected *** ./trier: free(): invalid pointer: 0xbf80594a ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb7e04d65]
/lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7e08800]
./trier[0x8048a83]
./trier[0x8048924]
./trier[0x804858a]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7db1050]
./trier[0x8048471]
======= Memory map: ========
08048000-08049000 r-xp 00000000 03:01 475185     /home/tatsou/Documents/chaine/trier
08049000-0804a000 rw-p 00000000 03:01 475185     /home/tatsou/Documents/chaine/trier
0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
b7c00000-b7c21000 rw-p b7c00000 00:00 0 
b7c21000-b7d00000 ---p b7c21000 00:00 0 
b7d9a000-b7d9b000 rw-p b7d9a000 00:00 0 
b7d9b000-b7edf000 r-xp 00000000 03:01 99445      /lib/tls/i686/cmov/libc-2.6.1.so
b7edf000-b7ee0000 r--p 00143000 03:01 99445      /lib/tls/i686/cmov/libc-2.6.1.so
b7ee0000-b7ee2000 rw-p 00144000 03:01 99445      /lib/tls/i686/cmov/libc-2.6.1.so
b7ee2000-b7ee5000 rw-p b7ee2000 00:00 0 
b7ee5000-b7eef000 r-xp 00000000 03:01 65603      /lib/libgcc_s.so.1
b7eef000-b7ef0000 rw-p 0000a000 03:01 65603      /lib/libgcc_s.so.1
b7ef0000-b7ef3000 rw-p b7ef0000 00:00 0 
b7ef3000-b7f0d000 r-xp 00000000 03:01 65549      /lib/ld-2.6.1.so
b7f0d000-b7f0f000 rw-p 00019000 03:01 65549      /lib/ld-2.6.1.so
bf7f1000-bf808000 rw-p bf7f1000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
b(null)Abandon (core dumped)

Hors ligne

#7 Le 20/11/2007, à 22:23

telliam

Re : [Résolu] Programme en C: erreur de segmentation.

apparemment tu fournis un pointeur invalide au moment de libérer la mémoire.
essaye de le lancer avec gdb normalement en remontant la pile d'appel, tu devrais pouvoir afficher les données et les pointeurs


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#8 Le 21/11/2007, à 01:57

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

void insererValeur (char *s)
{
   strcpy(t[dernier_calculer],s);
}

Hors ligne

#9 Le 21/11/2007, à 03:00

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

@nicolas.sitbon: Oula, oui tu as raison, mais cela ne corrige pas mon erreur.

J'ai fait un gdb et il semblerait que le problème apparaisse à  cet endroit:

void
reorganiserTasDes (unsigned sommet) {
  unsigned g = filsGauche(sommet);
  unsigned d = filsDroit(sommet);
  if (g != 0) {
    if (strcmp (t[sommet], t[g]) < 0) {          <==
      echanger (sommet, g);
      reorganiserTasDes(g);
    }
  }
  if (d != 0) {
    if (strcmp (t[sommet], t[d]) < 0){
      echanger (sommet, d);
      reorganiserTasDes(d);
    }
  }
}

Lors de l'execution de la ligne (pointé par la flèche), gdb m'affiche:

Program received signal SIGSEGV, Segmentation fault.
0xb7e7b028 in strcmp () from /lib/tls/i686/cmov/libc.so.6

A noter, au passage, que j'ai modifié ma fonction reorganiserTasDes.

Dernière modification par TatSou-Max (Le 21/11/2007, à 03:02)

Hors ligne

#10 Le 21/11/2007, à 09:03

telliam

Re : [Résolu] Programme en C: erreur de segmentation.

a mon avis les valeurs sommet ou g sont incorrects, non?


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#11 Le 21/11/2007, à 11:08

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

TatSou-Max a écrit :

voilà ce que j'attends de ce programme:

je rentre

./trier agj byuv  ecbfh dfhf

et le programme m'affiche

agj byuv dfhf ecbfh fkmp

J'avoue ne pas comprendre ce que tu attends de ton programme....

Hors ligne

#12 Le 21/11/2007, à 12:16

Picasso_tease

Re : [Résolu] Programme en C: erreur de segmentation.

Bonjour, smile

Le but de mon post est pour vous faire part de qqch assez etrange.
Je réalise une IHM en C++ avec des wxWidgets.
Apres plusieurs make et recitfication d'erreurs, j'ai une erreur de de segmentation.:mad:

Ma technique pour resoudre ce pb
Reboot
Make Clean
Make

.... et ca marche ! cool

Ne me demandez pas pourquoi ni comment.

Ciao


"Ce n'est pas assez d'avoir l'esprit bon, mais le principal est de l'appliquer bien"
DESCARTES, Discours de la methode.

Hors ligne

#13 Le 21/11/2007, à 13:05

telliam

Re : [Résolu] Programme en C: erreur de segmentation.

Picasso_tease a écrit :

Bonjour, smile

Le but de mon post est pour vous faire part de qqch assez etrange.
Je réalise une IHM en C++ avec des wxWidgets.
Apres plusieurs make et recitfication d'erreurs, j'ai une erreur de de segmentation.:mad:

Ma technique pour resoudre ce pb
Reboot
Make Clean
Make

.... et ca marche ! cool

Ne me demandez pas pourquoi ni comment.

Ciao

tu dois avoir un ecrasement mémoire ou un pointeur invalide qui de temps en temps ne tombe pas sur une valeur incorrecte, mais ton problème existe toujours...


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#14 Le 21/11/2007, à 13:49

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

nicolas.sitbon a écrit :

J'avoue ne pas comprendre ce que tu attends de ton programme....

Ben je veux trier des chaà®nes de caractères par ordre alphabétique.

Hors ligne

#15 Le 21/11/2007, à 13:51

Watchwolf

Re : [Résolu] Programme en C: erreur de segmentation.

compile avec l'option -g puis utilise gdb. Bien souvent un backtrace suffit pour résoudre les problemes.

Hors ligne

#16 Le 21/11/2007, à 13:51

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

nicolas.sitbon a écrit :
TatSou-Max a écrit :

voilà  ce que j'attends de ce programme:

je rentre

./trier agj byuv  ecbfh dfhf

et le programme m'affiche

agj byuv dfhf ecbfh fkmp

J'avoue ne pas comprendre ce que tu attends de ton programme....

alors d'ou sort "fkmp"?

Hors ligne

#17 Le 21/11/2007, à 14:01

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

Heu, en fait, c'est une erreur de copier coller hmm
Normalement, fkmp devrait aussi être en paramètre.


Et je compile déjà  avec l'option -g
Mon Makefile:

#le compilateur
CC= gcc

#les flags de compilation
CFLAGS= -g -Wall -pedantic-errors -Werror -std=c99

# les flags du preprocesseur
CPPFLAGS=

#les flags de l'editeur de lien 
LDFLAGS= 

#les librairies utilisees
LDLIBS= 

#Le nom du fichier executable
OUTFILE= trier

# les fichiers objets
OBJS=   implementation_tas.o trier.o memoire.o

# les dependances

all:  $(OUTFILE)

$(OUTFILE): $(OBJS)
# regle implicite utilisee par make pour l'edition de liens 
#	$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS)  -o $@


implementation_tas.o: implementation_tas.c implementation_tas.h memoire.h
trier.o:  trier.c implementation_tas.h
memoire.o: memoire.c memoire.h

# regle implicite utilisee par make pour la compilation
#	$(CC)   $(CPPFLAGS) $(CFLAGS) -c  -o $@ $<


clean :
	rm -f $(OBJS) $(OUTFILE)

Dernière modification par TatSou-Max (Le 21/11/2007, à 14:08)

Hors ligne

#18 Le 21/11/2007, à 14:46

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

J'avoue que je comprends mal pourquoi chercher à  réinventer la roue...pour manipuler des liste et des strings, le C++ et la Standard Template Library sont tout de même bien mieux indiqués...

Il me semble que ce petit bout de code:

#include <string>
#include <vector>
#include <iostream>

int main (int argc, char * argv[])
{
  std::vector<std::string>              liste;
  std::vector<std::string>::iterator    it;

  for (int i = 1; i < argc; i++)
  {
    liste.push_back(argv[i]);
  }

  sort(liste.begin(), liste.end());

  for (it = liste.begin(); it != liste.end(); it++)
  {
    std::cout << (*it) << " ";
  }
  std::cout << "\n";

  return 0;
}

fait à  peu près ce que tu voudrais faire...

Dernière modification par pipomolo (Le 21/11/2007, à 14:49)

Hors ligne

#19 Le 21/11/2007, à 15:06

nicolas.sitbon

Re : [Résolu] Programme en C: erreur de segmentation.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRSIZE 20

int main (int argc, char **argv)
{
   char (*tab)[STRSIZE] = malloc ((argc - 1) * sizeof *tab);
   for (int i = 1; i < argc; i++)
   {
      strncpy (tab[i - 1], argv[i], STRSIZE - 1);
      tab[i - 1][STRSIZE - 1] = '\0';
   }

   qsort (tab, argc - 1, STRSIZE, strcmp);

   for (int i = 0; i < argc - 1; i++)
   {
      printf ("%s ", tab[i]);
   }

   return 0;
}

marche aussi mais le but c'est d'apprendre.

Hors ligne

#20 Le 21/11/2007, à 15:07

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

Pourquoi chercher à  réinventer la roue ?
Voilà , une excellente question, mais le choix du langage C et de l'implémentation par Tas m'est imposé !

En plus, je pense sincèrement que mon programme est juste algorithmiquement parlant.
Mon souci c'est qu'à  chaque fois que je retourne dans mon code, j'en sors plus rien et je tourne en rond.

Dernière modification par TatSou-Max (Le 21/11/2007, à 15:19)

Hors ligne

#21 Le 21/11/2007, à 15:16

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

Dans ce cas, pourrais tu poster une petite archive tar.gz avec l'ensemble de ton code, histoire d'y jeter un coup d'oeil...car ça n'est pas évident à  lire sur le forum...

Hors ligne

#22 Le 21/11/2007, à 15:27

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

Voici l'archive tar.gz de tous les fichiers nécessaires à  la compilation (Makefile inclu):
Archive

Hors ligne

#23 Le 21/11/2007, à 16:23

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

ok, j'ai passé un petit coup de gdb, à  l'aide d'insight, et ça plante dans la fonction ReorganiserTasDes, au niveau du permier strcmp, sommet vaut 0 et t[0] est NULL ...donc le strcmp plante...

j'avoue que j'ai du mal à  comprendre ton implémentation de tas...j'aurais plutà´t utilisé une liste chaà®née pour faire un arbre...

Hors ligne

#24 Le 21/11/2007, à 16:29

TatSou-Max

Re : [Résolu] Programme en C: erreur de segmentation.

Ben dans mon cours d'algorithmique il est écrit en gras qu'un Tas doit toujours s'implémenter avec un tableau, donc voilà , j'ai fait un tableau.

Mais je ne comprends pas que t[0] soit NULL, car dans

char *
supprimerValeur (void) {
  char *racine = t[0];
  t[0] = t[dernier_calculer];
  return racine;
}

je mets le pointeur t[dernier_calculer] dans t[0] non ?
Donc a priori, je ne devrais pas avoir NULL ?

Hors ligne

#25 Le 21/11/2007, à 16:53

pipomolo

Re : [Résolu] Programme en C: erreur de segmentation.

sauf si t[dernier_calculer] est NULL wink

Hors ligne