J'ai un petit problème avec bsearch(), la fonction de comparaison
me renvoyant un segfault. Avant de poster ici, j'ai naturellement
vérifié avec valgrind qu'il n'y avait pas de corruption mémoire,
je n'ai rien trouvé. La même fonction de comparaison fonctionne
parfaitement (sur le même tableau) avec qsort().
Le prototype de struct_objet est le suivant :
typedef struct objet
{
enum t_type type;
integer8 extension_type;
void *descripteur_bibliotheque;
volatile long nombre_occurrences;
pthread_mutex_t mutex;
void *objet;
} struct_objet;
Seul nous intéresse ici le pointeur sur le void. En l'occurence,
lorsque l'objet contient une chaîne de caractère, ce pointeur est un
pointeur sur un unsigned char *.
Lorsque cet objet est un tableau, le pointeur tape sur une structure
struct_tableau définie comme :
Le bout de code en question crée un objet tableau contenant
quatre chaînes de caractères.
On a donc une structure S :
struct_objet -> struct_tableau -> elements(4)
Je réécris les fonctions qui posent problème. Il peut s'être
glissées des coquilles car j'ai simplifié les expressions (les
structures en mémoire sont beaucoup plus complexes que cela).
Ce tri fonctionne parfaitement et mon tableau est trié. Je
l'initialise pour mon test avec "key" "value" "i" "j", qsort()
retourne "i" "j" "key" "value".
J'essaie d'accéder à un élément particulier en utilisant bsearch() à
partir d'une autre fonction. J'utilise donc la même fonction
de comparaison. Avant d'appeler bsearch(), je vérifie que le contenu
de mon tableau est bon :
Et je me tape un segfault dans la fonction de comparaison. J'ai donc
investigué un peu plus loin en regardant les adresses passées à
cette fonction.
Lors du premier appel de la fonction de comparaison, le second
argument semble bon (il pointe sur l'une de mes chaînes) :
0x559c506f0a38->key
En revanche, le premier argument pointe sur n'importe quoi :
0x41048c200e47038d->Trying to catch access violation
Le message "Trying to catch access violation" provient du
gestionnaire de signaux.
Là, je ne comprends pas. J'ai beau reprendre les arguments de
bsearch(), je passe bien dans l'ordre la clef, le pointeur sur la
base du tableau, le nombre d'éléments du tableau, la taille de
chaque élément et un pointeur sur la fonction de comparaison. Et les
types sont les bons.
Je sèche. Toute idée sera la bienvenue.
Bien cordialement,
JKB
--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
=> http://loubardes.de-charybde-en-scylla.fr
Le 22/12/2018 à 15:22, Pascal J. Bourguignon a écrit :
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument introduire des abstraction fonctionnelles, et ne surtout pas utiliser partout des accès aux structures et des casts!
Méfiance!! Comme je le dis concernant du code légacy: on ne répare pas un code qui marche. Le mieux est l'ennemi du bien! Souvent en faisant mieux, on obtient bien pire parce qu'on considère comme mieux actuellement n'est pas forcément adapté au codes et aux machines de l'époque. Exemple: un GC c'est bien de nos jours, mais sur un ordi monocoeur il bloquera l’exécution de façon imprédictible ce qui posera des soucis avec un traitement "temps réel". a+ sam. --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
Le 22/12/2018 à 15:22, Pascal J. Bourguignon a écrit :
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument
introduire des abstraction fonctionnelles, et ne surtout pas utiliser
partout des accès aux structures et des casts!
Méfiance!! Comme je le dis concernant du code légacy: on ne répare pas
un code qui marche. Le mieux est l'ennemi du bien!
Souvent en faisant mieux, on obtient bien pire parce qu'on considère
comme mieux actuellement n'est pas forcément adapté au codes et aux
machines de l'époque. Exemple: un GC c'est bien de nos jours, mais sur
un ordi monocoeur il bloquera l’exécution de façon imprédictible ce qui
posera des soucis avec un traitement "temps réel".
a+
sam.
---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus
Le 22/12/2018 à 15:22, Pascal J. Bourguignon a écrit :
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument introduire des abstraction fonctionnelles, et ne surtout pas utiliser partout des accès aux structures et des casts!
Méfiance!! Comme je le dis concernant du code légacy: on ne répare pas un code qui marche. Le mieux est l'ennemi du bien! Souvent en faisant mieux, on obtient bien pire parce qu'on considère comme mieux actuellement n'est pas forcément adapté au codes et aux machines de l'époque. Exemple: un GC c'est bien de nos jours, mais sur un ordi monocoeur il bloquera l’exécution de façon imprédictible ce qui posera des soucis avec un traitement "temps réel". a+ sam. --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
Pascal J. Bourguignon
Samuel DEVULDER writes:
Le 22/12/2018 à 15:22, Pascal J. Bourguignon a écrit :
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument introduire des abstraction fonctionnelles, et ne surtout pas utiliser partout des accès aux structures et des casts!
Méfiance!! Comme je le dis concernant du code légacy: on ne r épare pas un code qui marche. Le mieux est l'ennemi du bien! Souvent en faisant mieux, on obtient bien pire parce qu'on considère comme mieux actuellement n'est pas forcément adapté au codes et aux machines de l'époque. Exemple: un GC c'est bien de nos jours, mais s ur un ordi monocoeur il bloquera l’exécution de façon impr édictible ce qui posera des soucis avec un traitement "temps réel".
On parle de code legacy, pas d'ordinateur legacy. S'il s'agit de faire tourner de vielles machines, c'est sur, on ne va pas pouvoir moderniser beaucoup le logiciel. Déjà, il n'y aura p as les outils, ou ça va être une galère pour compiler les outils r écents sur les vieux systèmes, avec toutes les dépendences, etc. Mais reprendre du vieux code sur un système moderne, dans la mesure des besoins, on peu le faire évoluer drastiquement. Le seul cas où c'est difficile, c'est quand on veut du bogue-pour-bogu e, car il est en effet facile d'éliminer beaucoup de bogues en le faisant évoluer proprement… -- __Pascal J. Bourguignon__ http://www.informatimago.com
Samuel DEVULDER <samuel-dot-devulder@laposte-dot-net.invalid> writes:
Le 22/12/2018 à 15:22, Pascal J. Bourguignon a écrit :
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument
introduire des abstraction fonctionnelles, et ne surtout pas utiliser
partout des accès aux structures et des casts!
Méfiance!! Comme je le dis concernant du code légacy: on ne r épare pas
un code qui marche. Le mieux est l'ennemi du bien!
Souvent en faisant mieux, on obtient bien pire parce qu'on considère
comme mieux actuellement n'est pas forcément adapté au codes et aux
machines de l'époque. Exemple: un GC c'est bien de nos jours, mais s ur
un ordi monocoeur il bloquera l’exécution de façon impr édictible ce
qui posera des soucis avec un traitement "temps réel".
On parle de code legacy, pas d'ordinateur legacy.
S'il s'agit de faire tourner de vielles machines, c'est sur, on ne va
pas pouvoir moderniser beaucoup le logiciel. Déjà, il n'y aura p as les
outils, ou ça va être une galère pour compiler les outils r écents sur
les vieux systèmes, avec toutes les dépendences, etc.
Mais reprendre du vieux code sur un système moderne, dans la mesure des
besoins, on peu le faire évoluer drastiquement.
Le seul cas où c'est difficile, c'est quand on veut du bogue-pour-bogu e,
car il est en effet facile d'éliminer beaucoup de bogues en le faisant
évoluer proprement…
--
__Pascal J. Bourguignon__
http://www.informatimago.com
Le 22/12/2018 à 15:22, Pascal J. Bourguignon a écrit :
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument introduire des abstraction fonctionnelles, et ne surtout pas utiliser partout des accès aux structures et des casts!
Méfiance!! Comme je le dis concernant du code légacy: on ne r épare pas un code qui marche. Le mieux est l'ennemi du bien! Souvent en faisant mieux, on obtient bien pire parce qu'on considère comme mieux actuellement n'est pas forcément adapté au codes et aux machines de l'époque. Exemple: un GC c'est bien de nos jours, mais s ur un ordi monocoeur il bloquera l’exécution de façon impr édictible ce qui posera des soucis avec un traitement "temps réel".
On parle de code legacy, pas d'ordinateur legacy. S'il s'agit de faire tourner de vielles machines, c'est sur, on ne va pas pouvoir moderniser beaucoup le logiciel. Déjà, il n'y aura p as les outils, ou ça va être une galère pour compiler les outils r écents sur les vieux systèmes, avec toutes les dépendences, etc. Mais reprendre du vieux code sur un système moderne, dans la mesure des besoins, on peu le faire évoluer drastiquement. Le seul cas où c'est difficile, c'est quand on veut du bogue-pour-bogu e, car il est en effet facile d'éliminer beaucoup de bogues en le faisant évoluer proprement… -- __Pascal J. Bourguignon__ http://www.informatimago.com
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument introduire des abstraction fonctionnelles, et ne surtout pas utiliser partout des accès aux structures et des casts!
Generalement, si c'est du vrai code, ca va commencer par utiliser des techniques modernes de developpement, donc passer pas mal de temps a ecrire des tests unitaires et des tests d'integration ;)
In article <m2k1jzvhi3.fsf@despina.home>,
Pascal J. Bourguignon <pjb@informatimago.com> wrote:
Samuel DEVULDER <samuel-dot-devulder@laposte-dot-net.invalid> writes:
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument
introduire des abstraction fonctionnelles, et ne surtout pas utiliser
partout des accès aux structures et des casts!
Generalement, si c'est du vrai code, ca va commencer par utiliser des
techniques modernes de developpement, donc passer pas mal de temps a
ecrire des tests unitaires et des tests d'integration ;)
Enfin, pour s'en sortir, surtout avec du code legacy, il faut absolument introduire des abstraction fonctionnelles, et ne surtout pas utiliser partout des accès aux structures et des casts!
Generalement, si c'est du vrai code, ca va commencer par utiliser des techniques modernes de developpement, donc passer pas mal de temps a ecrire des tests unitaires et des tests d'integration ;)
Samuel DEVULDER
Le 24/12/2018 à 02:30, Pascal J. Bourguignon a écrit :
On parle de code legacy, pas d'ordinateur legacy.
Le "on ne répare pas un truc qui marche" et "le mieux est l'ennemi du bien" s'appliquent dans les deux cas. Combien de fois n'ai-je pas vu un logiciel moins bien marcher suite à une mise à jour... Et tout ca pour faire "mieux"... Moauis... sam. --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
Le 24/12/2018 à 02:30, Pascal J. Bourguignon a écrit :
On parle de code legacy, pas d'ordinateur legacy.
Le "on ne répare pas un truc qui marche" et "le mieux est l'ennemi du
bien" s'appliquent dans les deux cas. Combien de fois n'ai-je pas vu un
logiciel moins bien marcher suite à une mise à jour... Et tout ca pour
faire "mieux"... Moauis...
sam.
---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus
Le 24/12/2018 à 02:30, Pascal J. Bourguignon a écrit :
On parle de code legacy, pas d'ordinateur legacy.
Le "on ne répare pas un truc qui marche" et "le mieux est l'ennemi du bien" s'appliquent dans les deux cas. Combien de fois n'ai-je pas vu un logiciel moins bien marcher suite à une mise à jour... Et tout ca pour faire "mieux"... Moauis... sam. --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
David Larochette
Le 22-12-2018, JKB a écrit :
si j'avais le temps, je réécrirais cette application dans un langage plus approprié que le C. Au hasard, le C++ JKB
Dis, ça va ? Tu nous couves pas quelque-chose ?
Le 22-12-2018, JKB <jkb@koenigsberg.invalid> a écrit :
si j'avais le temps, je
réécrirais cette application dans un langage plus approprié que le C. Au
hasard, le C++
si j'avais le temps, je réécrirais cette application dans un langage plus approprié que le C. Au hasard, le C++ JKB
Dis, ça va ? Tu nous couves pas quelque-chose ?
Samuel DEVULDER
Le 22/12/2018 à 23:24, JKB a écrit :
je réécrirais cette application dans un langage plus approprié que le C. Au hasard, le C++
$ cat c_vs_cxx.c #include <stdio.h> void main(void) { int c=3; printf("c=%dn", c); printf("c++=%dn", c++); } $ cc c_vs_cxx.c $ ./a.out c=3 c++=3 $ exit Humm de ce que j'en vois, même si on a l'impression d'avoir un coup d'avance avec le c++, en pratique c et c++ valent la même chose... sam :D --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
Le 22/12/2018 à 23:24, JKB a écrit :
je
réécrirais cette application dans un langage plus approprié que le C. Au
hasard, le C++
$ cat c_vs_cxx.c
#include <stdio.h>
void main(void) {
int c=3;
printf("c=%dn", c);
printf("c++=%dn", c++);
}
$ cc c_vs_cxx.c
$ ./a.out
c=3
c++=3
$ exit
Humm de ce que j'en vois, même si on a l'impression d'avoir un coup
d'avance avec le c++, en pratique c et c++ valent la même chose...
sam :D
---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus
je réécrirais cette application dans un langage plus approprié que le C. Au hasard, le C++
$ cat c_vs_cxx.c #include <stdio.h> void main(void) { int c=3; printf("c=%dn", c); printf("c++=%dn", c++); } $ cc c_vs_cxx.c $ ./a.out c=3 c++=3 $ exit Humm de ce que j'en vois, même si on a l'impression d'avoir un coup d'avance avec le c++, en pratique c et c++ valent la même chose... sam :D --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
Pascal J. Bourguignon
Samuel DEVULDER writes:
Le 22/12/2018 à 23:24, JKB a écrit :
je réécrirais cette application dans un langage plus approprié que le C. Au hasard, le C++
$ cat c_vs_cxx.c #include <stdio.h> void main(void) { int c=3; printf("c=%dn", c); printf("c++=%dn", c++); } $ cc c_vs_cxx.c $ ./a.out c=3 c++=3 $ exit Humm de ce que j'en vois, même si on a l'impression d'avoir un coup d'avance avec le c++, en pratique c et c++ valent la même chose... sam :D
Il doit y avoir une bogue. J'obtiens ça comme résultat: #include <stdio.h> void main(void) { int c=3; int cpp=c++; printf("c++ = %dn", cpp); printf("c = %dn", c); printf("c %s c++n", (c<cpp)?"<":((c>cpp)?">":"==")); } -*- mode: compilation; default-directory: "~/src/c/" -*- Compilation started at Thu Dec 27 00:21:15 SRC="/Users/pjb/src/c/c-vs-c++.c" ; EXE="c-vs-c++" ; gcc -I. -L. -g3 -ggdb3 -o ${EXE} ${SRC} && ./${EXE} && echo status = $? c++ = 3 c = 4 c > c++ Compilation exited abnormally with code 8 at Thu Dec 27 00:21:16 -- __Pascal J. Bourguignon__ http://www.informatimago.com
Samuel DEVULDER <samuel-dot-devulder@laposte-dot-net.invalid> writes:
Le 22/12/2018 à 23:24, JKB a écrit :
je
réécrirais cette application dans un langage plus approprié que le C. Au
hasard, le C++
$ cat c_vs_cxx.c
#include <stdio.h>
void main(void) {
int c=3;
printf("c=%dn", c);
printf("c++=%dn", c++);
}
$ cc c_vs_cxx.c
$ ./a.out
c=3
c++=3
$ exit
Humm de ce que j'en vois, même si on a l'impression d'avoir un coup
d'avance avec le c++, en pratique c et c++ valent la même chose...
sam :D
Il doit y avoir une bogue. J'obtiens ça comme résultat:
#include <stdio.h>
void main(void) {
int c=3;
int cpp=c++;
printf("c++ = %dn", cpp);
printf("c = %dn", c);
printf("c %s c++n", (c<cpp)?"<":((c>cpp)?">":"=="));
}
-*- mode: compilation; default-directory: "~/src/c/" -*-
Compilation started at Thu Dec 27 00:21:15
SRC="/Users/pjb/src/c/c-vs-c++.c" ; EXE="c-vs-c++" ; gcc -I. -L. -g3 -ggdb3 -o ${EXE} ${SRC} && ./${EXE} && echo status = $?
c++ = 3
c = 4
c > c++
Compilation exited abnormally with code 8 at Thu Dec 27 00:21:16
--
__Pascal J. Bourguignon__
http://www.informatimago.com
je réécrirais cette application dans un langage plus approprié que le C. Au hasard, le C++
$ cat c_vs_cxx.c #include <stdio.h> void main(void) { int c=3; printf("c=%dn", c); printf("c++=%dn", c++); } $ cc c_vs_cxx.c $ ./a.out c=3 c++=3 $ exit Humm de ce que j'en vois, même si on a l'impression d'avoir un coup d'avance avec le c++, en pratique c et c++ valent la même chose... sam :D
Il doit y avoir une bogue. J'obtiens ça comme résultat: #include <stdio.h> void main(void) { int c=3; int cpp=c++; printf("c++ = %dn", cpp); printf("c = %dn", c); printf("c %s c++n", (c<cpp)?"<":((c>cpp)?">":"==")); } -*- mode: compilation; default-directory: "~/src/c/" -*- Compilation started at Thu Dec 27 00:21:15 SRC="/Users/pjb/src/c/c-vs-c++.c" ; EXE="c-vs-c++" ; gcc -I. -L. -g3 -ggdb3 -o ${EXE} ${SRC} && ./${EXE} && echo status = $? c++ = 3 c = 4 c > c++ Compilation exited abnormally with code 8 at Thu Dec 27 00:21:16 -- __Pascal J. Bourguignon__ http://www.informatimago.com
Samuel DEVULDER
Le 27/12/2018 à 00:22, Pascal J. Bourguignon a écrit :
Il doit y avoir une bogue.
hmm... voyons...
J'obtiens ça comme résultat: #include <stdio.h> void main(void) { int c=3; int cpp=c++; printf("c++ = %dn", cpp); printf("c = %dn", c); printf("c %s c++n", (c<cpp)?"<":((c>cpp)?">":"==")); }
Normal, c'est pas le même programme, il ne fait absolument pas la même chose. Je ne le redirais jamais assez: On ne réparer pas un truc qui marche, sinon a on toutes les chances d'introduire des bugs, ce qui est le cas ici. a+ sam ;) --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
Le 27/12/2018 à 00:22, Pascal J. Bourguignon a écrit :
Il doit y avoir une bogue.
hmm... voyons...
J'obtiens ça comme résultat:
#include <stdio.h>
void main(void) {
int c=3;
int cpp=c++;
printf("c++ = %dn", cpp);
printf("c = %dn", c);
printf("c %s c++n", (c<cpp)?"<":((c>cpp)?">":"=="));
}
Normal, c'est pas le même programme, il ne fait absolument pas la même
chose. Je ne le redirais jamais assez: On ne réparer pas un truc qui
marche, sinon a on toutes les chances d'introduire des bugs, ce qui est
le cas ici.
a+
sam ;)
---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus
Le 27/12/2018 à 00:22, Pascal J. Bourguignon a écrit :
Il doit y avoir une bogue.
hmm... voyons...
J'obtiens ça comme résultat: #include <stdio.h> void main(void) { int c=3; int cpp=c++; printf("c++ = %dn", cpp); printf("c = %dn", c); printf("c %s c++n", (c<cpp)?"<":((c>cpp)?">":"==")); }
Normal, c'est pas le même programme, il ne fait absolument pas la même chose. Je ne le redirais jamais assez: On ne réparer pas un truc qui marche, sinon a on toutes les chances d'introduire des bugs, ce qui est le cas ici. a+ sam ;) --- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus
Bonjour à tous, J'ai un petit problème avec bsearch(), la fonction de comparaison me renvoyant un segfault. Avant de poster ici, j'ai naturellement vérifié avec valgrind qu'il n'y avait pas de corruption mémoire, je n'ai rien trouvé. La même fonction de comparaison fonctionne parfaitement (sur le même tableau) avec qsort(). J'ai écrit ceci : static int fonction_comparaison(const void *argument_1, const void *argument_2) { return(strcmp((unsigned char *) (**((struct_objet **) argument_1)).objet, (unsigned char *) (**((struct_objet **) argument_2)).objet)); } Le prototype de struct_objet est le suivant : typedef struct objet { enum t_type type; integer8 extension_type; void *descripteur_bibliotheque; volatile long nombre_occurrences; pthread_mutex_t mutex; void *objet; } struct_objet; Seul nous intéresse ici le pointeur sur le void. En l'occurence, lorsque l'objet contient une chaîne de caractère, ce pointeur est un pointeur sur un unsigned char *. Lorsque cet objet est un tableau, le pointeur tape sur une structure struct_tableau définie comme : typedef struct tableau { integer8 nombre_elements; struct_objet **elements; } struct_tableau; Le type integer8 est un entier 64 bits. Le bout de code en question crée un objet tableau contenant quatre chaînes de caractères. On a donc une structure S : struct_objet -> struct_tableau -> elements(4) Je réécris les fonctions qui posent problème. Il peut s'être glissées des coquilles car j'ai simplifié les expressions (les structures en mémoire sont beaucoup plus complexes que cela). qsort(((struct_tableau *) S->objet)->elements, (size_t) ((struct_tableau *) S->objet)->nombre_elements, sizeof(struct_objet *), fonction_comparaison); Ce tri fonctionne parfaitement et mon tableau est trié. Je l'initialise pour mon test avec "key" "value" "i" "j", qsort() retourne "i" "j" "key" "value". J'essaie d'accéder à un élément particulier en utilisant bsearch() à partir d'une autre fonction. J'utilise donc la même fonction de comparaison. Avant d'appeler bsearch(), je vérifie que le contenu de mon tableau est bon : (indice->adresse (chaîne)) 0->0x559c5070b3c8 (i) 1->0x559c50712958 (j) 2->0x559c506f0a38 (key) 3->0x559c506f09f8 (value) 0x559c506f0a38->key Cette sortie est faite par : for(i = 0; i < ((struct_tableau *) S->objet).nombre_elements; printf("%d->%p (%s)n", i, (unsigned char *) ((struct_tableau*) S->objet)->elements[i])->objet, (unsigned char *) ((struct_tableau*) S->objet)->elements[i])->objet, i++); Le nombre d'éléments est correct, le contenu des chaînes est bon. Valgrind ne rale pas. J'appelle donc bsearch() de la manière suivante (clef est initialisée un peu plus haut) : s_objet_element = bsearch((unsigned char *) clef, ((struct_tableau *) S->objet)->elements, (size_t) ((struct_tableau *) S->objet)->nombre_elements, sizeof(struct_objet *), fonction_comparaison); Et je me tape un segfault dans la fonction de comparaison. J'ai donc investigué un peu plus loin en regardant les adresses passées à cette fonction. Lors du premier appel de la fonction de comparaison, le second argument semble bon (il pointe sur l'une de mes chaînes) : 0x559c506f0a38->key En revanche, le premier argument pointe sur n'importe quoi : 0x41048c200e47038d->Trying to catch access violation Le message "Trying to catch access violation" provient du gestionnaire de signaux. Là, je ne comprends pas. J'ai beau reprendre les arguments de bsearch(), je passe bien dans l'ordre la clef, le pointeur sur la base du tableau, le nombre d'éléments du tableau, la taille de chaque élément et un pointeur sur la fonction de comparaison. Et les types sont les bons. Je sèche. Toute idée sera la bienvenue. Bien cordialement, JKB -- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr => http://loubardes.de-charybde-en-scylla.fr
Je pense qu"il serait sougaitable de voir votre code en entier. Cependant je vius donne les indications suivantes; La fonction de bibliothèque C void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *)) function search an array of nitems objects, which the initial member is pointed to by base, pour un membre qui correspond à l’objet pointé, par clé. La taille de chaque membre du tableau est spécifiée par la taille. Le contenu du tableau doit être en ordre croissant selon la fonction de comparaison référencée par compar. Déclaration : Voici la déclaration pour la fonction bsearch(). void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *) Cette fonction utilise les paramètres ci-dessois : Paramètres : key − Il s’agit du pointeur de l’objet qui sert de clé pour la recherche, caster comme un vide*. base − Il s’agit du pointeur vers le premier objet du tableau où la recherche est effectuée, lancé en tant que vide*. nitems − Il s’agit du nombre d’éléments dans le tableau pointé par la base. size − Il s’agit de la taille en octets de chaque élément du tableau. compare − C’est la fonction qui compare deux éléments. Valeur de retour : Cette fonction renvoie un pointeur à une entrée dans le tableau qui correspond à la clé de recherche. Si la clé n’est pas trouvée, un pointeur NULL est retourné.
Le samedi 22 Décembre 2018 à 10:22 par JKB :
> Bonjour à tous,
>
> J'ai un petit problème avec bsearch(), la fonction de comparaison
> me renvoyant un segfault. Avant de poster ici, j'ai naturellement
> vérifié avec valgrind qu'il n'y avait pas de corruption
> mémoire,
> je n'ai rien trouvé. La même fonction de comparaison fonctionne
> parfaitement (sur le même tableau) avec qsort().
>
> J'ai écrit ceci :
>
> static int
> fonction_comparaison(const void *argument_1, const void *argument_2)
> {
> return(strcmp((unsigned char *) (**((struct_objet **) argument_1)).objet,
> (unsigned char *) (**((struct_objet **) argument_2)).objet));
> }
>
> Le prototype de struct_objet est le suivant :
> typedef struct objet
> {
> enum t_type type;
> integer8 extension_type;
> void *descripteur_bibliotheque;
> volatile long nombre_occurrences;
> pthread_mutex_t mutex;
> void *objet;
> } struct_objet;
>
> Seul nous intéresse ici le pointeur sur le void. En l'occurence,
> lorsque l'objet contient une chaîne de caractère, ce pointeur est
> un
> pointeur sur un unsigned char *.
>
> Lorsque cet objet est un tableau, le pointeur tape sur une structure
> struct_tableau définie comme :
>
> typedef struct tableau
> {
> integer8 nombre_elements;
> struct_objet **elements;
> } struct_tableau;
>
> Le type integer8 est un entier 64 bits.
>
> Le bout de code en question crée un objet tableau contenant
> quatre chaînes de caractères.
>
> On a donc une structure S :
>
> struct_objet -> struct_tableau -> elements(4)
>
> Je réécris les fonctions qui posent problème. Il peut
> s'être
> glissées des coquilles car j'ai simplifié les expressions (les
> structures en mémoire sont beaucoup plus complexes que cela).
>
> qsort(((struct_tableau *) S->objet)->elements,
> (size_t) ((struct_tableau *) S->objet)->nombre_elements,
> sizeof(struct_objet *),
> fonction_comparaison);
>
> Ce tri fonctionne parfaitement et mon tableau est trié. Je
> l'initialise pour mon test avec "key" "value"
> "i" "j", qsort()
> retourne "i" "j" "key" "value".
>
> J'essaie d'accéder à un élément particulier en
> utilisant bsearch() à
> partir d'une autre fonction. J'utilise donc la même fonction
> de comparaison. Avant d'appeler bsearch(), je vérifie que le contenu
> de mon tableau est bon :
>
> (indice->adresse (chaîne))
>
> 0->0x559c5070b3c8 (i)
> 1->0x559c50712958 (j)
> 2->0x559c506f0a38 (key)
> 3->0x559c506f09f8 (value)
> 0x559c506f0a38->key
>
> Cette sortie est faite par :
>
> for(i = 0; i < ((struct_tableau *) S->objet).nombre_elements;
> printf("%d->%p (%s)n", i,
> (unsigned char *) ((struct_tableau*)
> S->objet)->elements[i])->objet,
> (unsigned char *) ((struct_tableau*)
> S->objet)->elements[i])->objet,
> i++);
>
> Le nombre d'éléments est correct, le contenu des chaînes
> est bon.
> Valgrind ne rale pas.
>
> J'appelle donc bsearch() de la manière suivante (clef est
> initialisée un peu plus haut) :
>
> s_objet_element = bsearch((unsigned char *) clef,
> ((struct_tableau *) S->objet)->elements,
> (size_t) ((struct_tableau *) S->objet)->nombre_elements,
> sizeof(struct_objet *), fonction_comparaison);
>
> Et je me tape un segfault dans la fonction de comparaison. J'ai donc
> investigué un peu plus loin en regardant les adresses passées
> à
> cette fonction.
>
> Lors du premier appel de la fonction de comparaison, le second
> argument semble bon (il pointe sur l'une de mes chaînes) :
>
> 0x559c506f0a38->key
>
> En revanche, le premier argument pointe sur n'importe quoi :
>
> 0x41048c200e47038d->Trying to catch access violation
>
> Le message "Trying to catch access violation" provient du
> gestionnaire de signaux.
>
> Là, je ne comprends pas. J'ai beau reprendre les arguments de
> bsearch(), je passe bien dans l'ordre la clef, le pointeur sur la
> base du tableau, le nombre d'éléments du tableau, la taille de
> chaque élément et un pointeur sur la fonction de comparaison. Et
> les
> types sont les bons.
>
> Je sèche. Toute idée sera la bienvenue.
>
> Bien cordialement,
>
> JKB
>
> --
> Si votre demande me parvient sur carte perforée, je titiouaillerai
> très
> volontiers une réponse...
> => http://grincheux.de-charybde-en-scylla.fr
> => http://loubardes.de-charybde-en-scylla.fr
Je pense qu"il serait sougaitable de voir votre code en entier. Cependant je vius donne les indications suivantes;
La fonction de bibliothèque C void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *)) function search an array of nitems objects, which the initial member is pointed to by base, pour un membre qui correspond à l’objet pointé, par clé. La taille de chaque membre du tableau est spécifiée par la taille.
Le contenu du tableau doit être en ordre croissant selon la fonction de comparaison référencée par compar.
Déclaration :
Voici la déclaration pour la fonction bsearch().
void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *)
Cette fonction utilise les paramètres ci-dessois :
Paramètres :
key − Il s’agit du pointeur de l’objet qui sert de clé pour la recherche, caster comme un vide*.
base − Il s’agit du pointeur vers le premier objet du tableau où la recherche est effectuée, lancé en tant que vide*.
nitems − Il s’agit du nombre d’éléments dans le tableau pointé par la base.
size − Il s’agit de la taille en octets de chaque élément du tableau.
compare − C’est la fonction qui compare deux éléments.
Valeur de retour :
Cette fonction renvoie un pointeur à une entrée dans le tableau qui correspond à la clé de recherche. Si la clé n’est pas trouvée, un pointeur NULL est retourné.
Bonjour à tous, J'ai un petit problème avec bsearch(), la fonction de comparaison me renvoyant un segfault. Avant de poster ici, j'ai naturellement vérifié avec valgrind qu'il n'y avait pas de corruption mémoire, je n'ai rien trouvé. La même fonction de comparaison fonctionne parfaitement (sur le même tableau) avec qsort(). J'ai écrit ceci : static int fonction_comparaison(const void *argument_1, const void *argument_2) { return(strcmp((unsigned char *) (**((struct_objet **) argument_1)).objet, (unsigned char *) (**((struct_objet **) argument_2)).objet)); } Le prototype de struct_objet est le suivant : typedef struct objet { enum t_type type; integer8 extension_type; void *descripteur_bibliotheque; volatile long nombre_occurrences; pthread_mutex_t mutex; void *objet; } struct_objet; Seul nous intéresse ici le pointeur sur le void. En l'occurence, lorsque l'objet contient une chaîne de caractère, ce pointeur est un pointeur sur un unsigned char *. Lorsque cet objet est un tableau, le pointeur tape sur une structure struct_tableau définie comme : typedef struct tableau { integer8 nombre_elements; struct_objet **elements; } struct_tableau; Le type integer8 est un entier 64 bits. Le bout de code en question crée un objet tableau contenant quatre chaînes de caractères. On a donc une structure S : struct_objet -> struct_tableau -> elements(4) Je réécris les fonctions qui posent problème. Il peut s'être glissées des coquilles car j'ai simplifié les expressions (les structures en mémoire sont beaucoup plus complexes que cela). qsort(((struct_tableau *) S->objet)->elements, (size_t) ((struct_tableau *) S->objet)->nombre_elements, sizeof(struct_objet *), fonction_comparaison); Ce tri fonctionne parfaitement et mon tableau est trié. Je l'initialise pour mon test avec "key" "value" "i" "j", qsort() retourne "i" "j" "key" "value". J'essaie d'accéder à un élément particulier en utilisant bsearch() à partir d'une autre fonction. J'utilise donc la même fonction de comparaison. Avant d'appeler bsearch(), je vérifie que le contenu de mon tableau est bon : (indice->adresse (chaîne)) 0->0x559c5070b3c8 (i) 1->0x559c50712958 (j) 2->0x559c506f0a38 (key) 3->0x559c506f09f8 (value) 0x559c506f0a38->key Cette sortie est faite par : for(i = 0; i < ((struct_tableau *) S->objet).nombre_elements; printf("%d->%p (%s)n", i, (unsigned char *) ((struct_tableau*) S->objet)->elements[i])->objet, (unsigned char *) ((struct_tableau*) S->objet)->elements[i])->objet, i++); Le nombre d'éléments est correct, le contenu des chaînes est bon. Valgrind ne rale pas. J'appelle donc bsearch() de la manière suivante (clef est initialisée un peu plus haut) : s_objet_element = bsearch((unsigned char *) clef, ((struct_tableau *) S->objet)->elements, (size_t) ((struct_tableau *) S->objet)->nombre_elements, sizeof(struct_objet *), fonction_comparaison); Et je me tape un segfault dans la fonction de comparaison. J'ai donc investigué un peu plus loin en regardant les adresses passées à cette fonction. Lors du premier appel de la fonction de comparaison, le second argument semble bon (il pointe sur l'une de mes chaînes) : 0x559c506f0a38->key En revanche, le premier argument pointe sur n'importe quoi : 0x41048c200e47038d->Trying to catch access violation Le message "Trying to catch access violation" provient du gestionnaire de signaux. Là, je ne comprends pas. J'ai beau reprendre les arguments de bsearch(), je passe bien dans l'ordre la clef, le pointeur sur la base du tableau, le nombre d'éléments du tableau, la taille de chaque élément et un pointeur sur la fonction de comparaison. Et les types sont les bons. Je sèche. Toute idée sera la bienvenue. Bien cordialement, JKB -- Si votre demande me parvient sur carte perforée, je titiouaillerai très volontiers une réponse... => http://grincheux.de-charybde-en-scylla.fr => http://loubardes.de-charybde-en-scylla.fr
Je pense qu"il serait sougaitable de voir votre code en entier. Cependant je vius donne les indications suivantes; La fonction de bibliothèque C void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *)) function search an array of nitems objects, which the initial member is pointed to by base, pour un membre qui correspond à l’objet pointé, par clé. La taille de chaque membre du tableau est spécifiée par la taille. Le contenu du tableau doit être en ordre croissant selon la fonction de comparaison référencée par compar. Déclaration : Voici la déclaration pour la fonction bsearch(). void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *) Cette fonction utilise les paramètres ci-dessois : Paramètres : key − Il s’agit du pointeur de l’objet qui sert de clé pour la recherche, caster comme un vide*. base − Il s’agit du pointeur vers le premier objet du tableau où la recherche est effectuée, lancé en tant que vide*. nitems − Il s’agit du nombre d’éléments dans le tableau pointé par la base. size − Il s’agit de la taille en octets de chaque élément du tableau. compare − C’est la fonction qui compare deux éléments. Valeur de retour : Cette fonction renvoie un pointeur à une entrée dans le tableau qui correspond à la clé de recherche. Si la clé n’est pas trouvée, un pointeur NULL est retourné.