Ou est l'erreur de segmentation ? - C - Programmation
Marsh Posté le 07-08-2006 à 14:31:05
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
Marsh Posté le 07-08-2006 à 14:36:36
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).
Marsh Posté le 07-08-2006 à 16:21:29
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...
Marsh Posté le 07-08-2006 à 16:24:34
ReplyMarsh Posté le 07-08-2006 à 16:29:18
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...
Marsh Posté le 07-08-2006 à 16:30:33
Sve@r a écrit : Exact. J'ai mal regardé - Je rectifie mon post précédent... |
ben comme le dit franceso, en passant des char** à strcmp(), on n'obtient pas le comportement attendu.
Marsh Posté le 07-08-2006 à 16:34:25
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...
Marsh Posté le 07-08-2006 à 16:34:46
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
Marsh Posté le 07-08-2006 à 16:40:57
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).
Marsh Posté le 07-08-2006 à 16:43:46
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...
Edit: Pourquoi en ligne 44 du pgm initial le "étoile" est entre parenthèses tout seul ?
Citation :
|
Moi je verrais mieux
Code :
|
Mais je comprends rien à cette syntaxe alambiquée. Intuitivement, j'aurais simplement écrit
Code :
|
Marsh Posté le 07-08-2006 à 16:47:24
Sve@r a écrit : Exact. Bon, je suis pas au top today... vaut mieux que j'arrête de m'enfoncer tout seul... |
Marsh Posté le 07-08-2006 à 17:07:15
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
|
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...
Marsh Posté le 07-08-2006 à 17:11:09
En remplaçant :
Code :
|
par
Code :
|
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
Marsh Posté le 07-08-2006 à 17:12:21
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().
Marsh Posté le 07-08-2006 à 18:20:08
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).
Marsh Posté le 07-08-2006 à 18:53:23
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 :
|
et
Code :
|
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
Marsh Posté le 07-08-2006 à 19:07:16
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.
Marsh Posté le 07-08-2006 à 19:15:03
T1, l'examen d'obfuscated C code...
Marsh Posté le 07-08-2006 à 20:02:44
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');
Marsh Posté le 07-08-2006 à 21:22:01
franceso a écrit : J'ai essayé en mettant :
et
|
Ca marche très bien sans cast si tu mets des const char* au prototype de la fonction plutôt que des char*
Marsh Posté le 08-08-2006 à 09:08:43
ReplyMarsh Posté le 09-08-2006 à 23:00:07
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.
Marsh Posté le 09-08-2006 à 23:19:37
je pense que le compilo corrige lorsqu'il n'y a qu'une instruction. A vérifier
Marsh Posté le 10-08-2006 à 01:02:37
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
Marsh Posté le 10-08-2006 à 08:49:57
on peux surcharger les deux non ?
operator++ (); // prefix ++
operator++ (int); // postfix ++
Marsh Posté le 10-08-2006 à 10:21:56
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 ++
Marsh Posté le 07-08-2006 à 14:02:37
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
L'execution du programme suivant produit une erreur de segmentation. Expliquez pourquoi.
L'execution
Message édité par Gattuso le 07-08-2006 à 14:04:49