Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2690 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Ou est l'erreur de segmentation ?

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Ou est l'erreur de segmentation ?

n°1421454
Gattuso
Posté le 07-08-2006 à 14:02:37  profilanswer
 

Bonjour,
 
cet exo est tiré d'un examen qui a été donné dans la fac ou je suis.
Les erreurs sont censées être trouvées en lisant le code mais comme je ne trouvais rien d'anormal, j'ai compilé et exécuté le programme.
Aucune erreur de segmentation n'a été décelée.
Je voudrais donc savoir si quelqu'un voyait quelques choses d'anormal dans ce code car il doit vraiment y avoir une ou plusieurs erreurs car l'exo a été donné en examen  :)  
 

Citation :

L'execution du programme suivant produit une erreur de segmentation. Expliquez pourquoi.
L'execution

Code :
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. void bubbleSort(char **tab, int (*cmp)(void *, void *))
  5. {
  6.   char **p1, **p2;
  7.   for(p1=tab; *p1!=NULL; ++p1)
  8.     for(p2=p1+1; *p2!=NULL; ++p2)
  9.       if((*cmp)(p1,p2)>0)
  10. {
  11.   char *tmp;
  12.   tmp = *p1;
  13.   *p1 = *p2;
  14.   *p2 = tmp;
  15. }
  16. }
  17. void printTable(FILE *fdo, char **tab)
  18. {
  19.   for(; *tab!=NULL; ++tab) fprintf(fdo,"%s\n", *tab);
  20. }
  21. int main(int argc, char *argv[])
  22. {
  23.   char **t; unsigned int i,l;
  24.   if((t=(char**)malloc(sizeof(char*)*argc))==NULL)
  25.     {
  26.       fprintf(stderr,"Error in memory allocation\n" );
  27.       return EXIT_FAILURE;
  28.     }
  29.   l=(unsigned int)argc-1U;
  30.   for(i=0U; i<l; ++i)
  31.     {
  32.       if((t[i]=(char*)malloc(strlen(argv[i+1])+1))==NULL)
  33. {
  34.   fprintf(stderr,"Error in memory allocation\n" );
  35.   return EXIT_FAILURE;
  36. }
  37.       strcpy(t[i],argv[i+1]);
  38.     }
  39.   t[l]=NULL;
  40.   printTable(stdout,t);
  41.   bubbleSort(t, (int (*)(void *, void *))&strcmp);
  42.   printf("\n" );
  43.   printTable(stdout, t);
  44.   return EXIT_SUCCESS;
  45. }



Message édité par Gattuso le 07-08-2006 à 14:04:49
mood
Publicité
Posté le 07-08-2006 à 14:02:37  profilanswer
 

n°1421490
pains-aux-​raisins
Fatal error
Posté le 07-08-2006 à 14:31:05  profilanswer
 

Effectivement, à l'arrache, je ne vois pas trop le souci.
Il faut en tout cas bien examiner les affectations de pointeurs (strcpy, =) en fonction de la taille allouée pour chacun d'entre eux.
Je m'y repencherais si j'ai un peu de tps aujourd'hui

n°1421497
franceso
Posté le 07-08-2006 à 14:36:36  profilanswer
 

Je ne sais pas si c'est ce que ton prof attendait, mais il y a au moins une erreur dans la fonction bubbleSort, ligne 10.
Si je ne me trompe pas, il faut mettre  (*cmp)(*p1,*p2)  au lieu de (*cmp)(p1,p2).
 Dans tous les cas où j'ai testé, je n'ai pas eu de segfault, mais ce genre de choses pourrait bien en causer une. En tous cas, il est clair que le programme en l'état ne fait pas ce qu'on veut (à savoir trier la liste de ses arguments).


---------------
TriScale innov
n°1421622
Sve@r
Posté le 07-08-2006 à 16:21:29  profilanswer
 

franceso a écrit :

En tous cas, il est clair que le programme en l'état ne fait pas ce qu'on veut (à savoir trier la liste de ses arguments).


Hum... l'algo du bubblesort veut qu'on recommence le balayage tant qu'on a eu au-moins une permutation. Là, je ne vois pas de flag indiquant qu'il faut recommencer...

Message cité 1 fois
Message édité par Sve@r le 07-08-2006 à 16:41:56

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1421635
Elmoricq
Modérateur
Posté le 07-08-2006 à 16:24:34  profilanswer
 

euh, p1 et p2 sont des char**... je pense que franceso a raison.

n°1421646
Sve@r
Posté le 07-08-2006 à 16:29:18  profilanswer
 

Elmoricq a écrit :

euh, p1 et p2 sont des char**... je pense que franceso a raison.


Exact. J'ai mal regardé - Je rectifie mon post précédent...
En revanche, je ne vois pas trop l'erreur...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1421647
Elmoricq
Modérateur
Posté le 07-08-2006 à 16:30:33  profilanswer
 

Sve@r a écrit :

Exact. J'ai mal regardé - Je rectifie mon post précédent...
En revanche, je ne vois pas trop l'erreur...


 
ben comme le dit franceso, en passant des char** à strcmp(), on n'obtient pas le comportement attendu.

n°1421651
Sve@r
Posté le 07-08-2006 à 16:34:25  profilanswer
 

Elmoricq a écrit :

ben comme le dit franceso, en passant des char** à strcmp(), on n'obtient pas le comportement attendu.


Non, je comprends bien que si strcmp ne reçoit pas la bonne adresse il va pointer n'importe où. Ce que je ne voyais pas, c'est pourquoi l'algo même débugé par Francesco ne fonctionnait pas. Puis j'ai vu qu'il manquait le flag de répétition de balayage...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1421652
jagstang
Pa Capona ಠ_ಠ
Posté le 07-08-2006 à 16:34:46  profilanswer
 

Sve@r a écrit :

Hum... l'algo du bubblesort veut qu'on recommence le balayage tant qu'on a eu au-moins une permutation. Là, je ne vois pas de flag indiquant qu'il faut recommencer...


dans le bubble sort, on fait N passages (ou N est la taille du tableau).
 
edit : http://en.wikipedia.org/wiki/Bubble_sort


Message édité par jagstang le 07-08-2006 à 16:37:41

---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
n°1421657
franceso
Posté le 07-08-2006 à 16:40:57  profilanswer
 

Sve@r a écrit :

Non, je comprends bien que si strcmp ne reçoit pas la bonne adresse il va pointer n'importe où. Ce que je ne voyais pas, c'est pourquoi l'algo même débugé par Francesco ne fonctionnait pas. Puis j'ai vu qu'il manquait le flag de répétition de balayage...


Le flag de répétition du balayage n'est qu'une amélioration du bubblesort. Dans l'algo implémenté ici, on fait toujours N passages (ce qui est n'est en général pas nécessaire, mais suffit toujours pour trier tout le tableau).


---------------
TriScale innov
mood
Publicité
Posté le 07-08-2006 à 16:40:57  profilanswer
 

n°1421662
Sve@r
Posté le 07-08-2006 à 16:43:46  profilanswer
 

franceso a écrit :

Le flag de répétition du balayage n'est qu'une amélioration du bubblesort. Dans l'algo implémenté ici, on fait toujours N passages (ce qui est n'est en général pas nécessaire, mais suffit toujours pour trier tout le tableau).


Exact. Bon, je suis pas au top today... vaut mieux que j'arrête de m'enfoncer tout seul... :sol:
 
Edit: Pourquoi en ligne 44 du pgm initial le "étoile" est entre parenthèses tout seul ?

Citation :

Code :
  1. bubbleSort(t, (int (*)(void *, void *))&strcmp);



Moi je verrais mieux

Code :
  1. bubbleSort(t, int (*(void *, void *))&strcmp);


Mais je comprends rien à cette syntaxe alambiquée. Intuitivement, j'aurais simplement écrit

Code :
  1. bubbleSort(t, strcmp);


Message cité 2 fois
Message édité par Sve@r le 07-08-2006 à 16:54:40

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1421670
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 07-08-2006 à 16:47:24  profilanswer
 

Sve@r a écrit :

Exact. Bon, je suis pas au top today... vaut mieux que j'arrête de m'enfoncer tout seul... :sol:


[:lorill]


---------------
J'ai un string dans l'array (Paris Hilton)
n°1421688
franceso
Posté le 07-08-2006 à 17:07:15  profilanswer
 

Sve@r a écrit :

Edit: Pourquoi en ligne 44 du pgm initial le "étoile" est entre parenthèses tout seul ?

Je pense que c'est la seule syntaxe valide pour exprimer le cast vers un type fonction.
 

Sve@r a écrit :

Mais je comprends rien à cette syntaxe alambiquée. Intuitivement, j'aurais simplement écrit

Code :
  1. bubbleSort(t, strcmp);



C'est ce que j'aurais fait aussi intuitivement, mais je viens d'essayer et ça ne marche pas : le compilateur renvoit systématiquement un warning. C'est étrange : je ne vois pourtant pas ce qui est différent entre ce programme et quelque chose dans le genre de l'appel système "signal", pour lequel je n'ai jamais eu besoin de caster explicitement mes adresses de fonctions...


---------------
TriScale innov
n°1421691
Gattuso
Posté le 07-08-2006 à 17:11:09  profilanswer
 

En remplaçant :

Code :
  1. if((*cmp)(p1,p2)>0)


par  

Code :
  1. if((*cmp)(*p1,*p2)>0)


On obtient le tri des mots que l'on tape
 
Le fait d'avoir oublier l'* n'a pas l'air d'avoir une cause sur un éventuel seg fault car avec ou sans ça compile et ça s'éxécute.
J'ai executé en ne donnant aucun parametres puis plusieurs mais ça ne donne toujours pas de seg fault, c'est bizzare

n°1421692
Elmoricq
Modérateur
Posté le 07-08-2006 à 17:12:21  profilanswer
 

franceso a écrit :

Je pense que c'est la seule syntaxe valide pour exprimer le cast vers un type fonction.


C'est juste un cast je pense, parce que la fonction de tri accepte des void* et non des const char*, comme strcmp().

Message cité 1 fois
Message édité par Elmoricq le 07-08-2006 à 17:12:55
n°1421750
Trap D
Posté le 07-08-2006 à 18:20:08  profilanswer
 

Il faudrait peut-être libérer la mémoire allouée en fin de programme il me semble (mais ça ne provoque pas d'erreur de segmentation).

n°1421791
franceso
Posté le 07-08-2006 à 18:53:23  profilanswer
 

Elmoricq a écrit :

C'est juste un cast je pense, parce que la fonction de tri accepte des void* et non des const char*, comme strcmp().


J'ai essayé en mettant :

Code :
  1. void bubbleSort(char **tab, int (*cmp)(char *, char *))

et

Code :
  1. bubbleSort(t, (int (*)(void *, void *))&strcmp)


 
Normalement, je pensais que dans ce cas le cast explicite n'était pas obligatoire puisque strcmp est déjà une fonction du bon type, mais le compilateur donne quand même un warning. Etrange :/

Message cité 1 fois
Message édité par franceso le 07-08-2006 à 18:53:41

---------------
TriScale innov
n°1421802
franceso
Posté le 07-08-2006 à 19:07:16  profilanswer
 

Gattuso a écrit :

Le fait d'avoir oublier l'* n'a pas l'air d'avoir une cause sur un éventuel seg fault car avec ou sans ça compile et ça s'éxécute.


 
effectivement, dans les deux cas ça compile (normal puisque le prof a brouillé les pistes en donnant à la fonction de comparaison un type (void*,void*)->int qui peut accepter n'importe quoi comme paramètre).
 
Par contre, je pense que le fait que tout s'exécute bien est un gros coup de chance. Théoriquement, la fonction strcmp pourrait bien faire n'importe quoi (y compris des erreurs de segmentations si elle parcourt ce qu'elle pense être des chaines de caractères en cherchant désespérément un 0 final qu'elle n'a aucune raison de trouver).
 
Dans notre cas particulier, il se trouve qu'on est sur que *p1 != *p2 (puisque *p1 et *p2 sont les adresses de deux chaines de caractères différentes) donc lorsque strcmp compare ce qu'il pense être le premier caractère de chaque chaine, on compare deux valeurs débiles mais qui sont nécéssairement différentes donc strcmp renvoit tout de suite un résultat. Du coup, je pense que jamais on n'obtiendra de segfault avec ce programme, bien qu'il fasse n'importe quoi avec des pointeurs.


---------------
TriScale innov
n°1421814
farib
Posté le 07-08-2006 à 19:15:03  profilanswer
 

T1, l'examen d'obfuscated C code... [:k-nar]


Message édité par farib le 07-08-2006 à 19:15:14

---------------
Bitcoin, Magical Thinking, and Political Ideology
n°1421856
skelter
Posté le 07-08-2006 à 20:02:44  profilanswer
 

bubbleSort devrai prendre un 'int (*)(const char *, const char *)'
 
cast inutiles des malloc
 
l=(unsigned int)argc-1U; ??
-->
l=argc-1;
 
for(i=0U; i<l; ++i)
-->
for(i=0; i<l; i++) /* pourquoi faire autrement ? */
 
manque des const
 
la mémoire allouée dynamiquement n'est pas libérée (attention à la gestion des erreur)
 
printf("\n" );
-->
putchar('\n');


Message édité par skelter le 07-08-2006 à 20:03:05
n°1421896
Elmoricq
Modérateur
Posté le 07-08-2006 à 21:22:01  profilanswer
 

franceso a écrit :

J'ai essayé en mettant :

Code :
  1. void bubbleSort(char **tab, int (*cmp)(char *, char *))

et

Code :
  1. bubbleSort(t, (int (*)(void *, void *))&strcmp)


 
Normalement, je pensais que dans ce cas le cast explicite n'était pas obligatoire puisque strcmp est déjà une fonction du bon type, mais le compilateur donne quand même un warning. Etrange :/


 
Ca marche très bien sans cast si tu mets des const char* au prototype de la fonction plutôt que des char* ;)

n°1422070
franceso
Posté le 08-08-2006 à 09:08:43  profilanswer
 

efefctivement, j'avais oublié les const :sweat:


---------------
TriScale innov
n°1423305
Elmoricq
Modérateur
Posté le 09-08-2006 à 23:00:07  profilanswer
 

Sve@r a écrit :

Beaucoup préfèrent mettre "++i" qui est plus rapide que "i++"...


 
Demain je zieute le code assembleur entre les deux pour vérifier. [:fou]

n°1423317
jagstang
Pa Capona ಠ_ಠ
Posté le 09-08-2006 à 23:19:37  profilanswer
 

je pense que le compilo corrige lorsqu'il n'y a qu'une instruction. A vérifier

n°1423341
skelter
Posté le 10-08-2006 à 01:02:37  profilanswer
 

rien ne dit ca mais la plupart des compilo le font certainement, faut pas avoir inventé l'eau chaude
en gros ca ne sert a rien d'ecrire ++i a la place de i++ dans le seul but d'eviter la temp, il faut simplement utiliser l'un ou l'autre en fonction de la sémantique voulue
 
c'est en C++ qu'il faut faire attention, pour les types non-builtin, on peut surcharger ++ sans garantir la corrélation entre ++ post et pre donc le compilo ne peux pas optimiser

n°1423371
jagstang
Pa Capona ಠ_ಠ
Posté le 10-08-2006 à 08:49:57  profilanswer
 

on peux surcharger les deux non ?
 
operator++ ();    // prefix ++
operator++ (int); // postfix ++

n°1423448
skelter
Posté le 10-08-2006 à 10:21:56  profilanswer
 

ben oui, et tu peux les implémenter comme tu veux. la surcharge d'opérateur est libre en C++, on doit juste respecter le nombre d'opérande.
comme tu n'est pas obligé d'implémenter ++ post et pre de telle sorte que r++ <=> temp = r, ++r, temp et ++r <=> r += 1 faut surtout pas s'attendre à ce que le compilateur fasse ce genre d'optimisation.
 
on peut remarquer que le langage D ne permet de surcharger que ++ pre et garanti ces relations sémantiques de base, ce qui rend possible ce genre d'optimisation pour n'importe quel type surchargeant ++

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Ou est l'erreur de segmentation ?

 

Sujets relatifs
Erreur de SegmentationErreur de segmentation incompréhensible
erreur de segmentation"erreur de segmentation" avec les threads sous linux en C++
Erreur de segmentationerreur de segmentation sur string
Erreur SegmentationErreur de segmentation
erreur de segmentationerreur de segmentation pourtant simple
Plus de sujets relatifs à : Ou est l'erreur de segmentation ?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR