Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Problème bizarre

21 réponses
Avatar
JKB
Bonjour à tous,

Je sèche depuis ce matin sur un problème bizarre. Ça doit être
complètement trivial, mais je ne comprend pas. Considérons le code
suivant qui provient d'un analyseur syntaxique que j'ai écrit :

/*
* Test de la présence de l'instruction EXIT dans une boucle
*/

l_element_pile_systeme = (*s_etat_processus).l_base_pile_systeme;
presence_boucle = d_faux;
drapeau_boucle_definie = d_faux;

while((l_element_pile_systeme != NULL) &&
(printf(">%d\n", presence_boucle), presence_boucle == d_faux))
{
printf("Boucle %d\n", presence_boucle);
if ((strcmp((*l_element_pile_systeme).type_cloture, "START") == 0) ||
(strcmp((*l_element_pile_systeme).type_cloture, "FOR") == 0))
{
printf("Là\n");
presence_boucle = d_vrai;
drapeau_boucle_definie = d_vrai;
}
else if ((strcmp((*l_element_pile_systeme).type_cloture, "DO") == 0) ||
(strcmp((*l_element_pile_systeme).type_cloture, "WHILE") == 0))
{
printf("Ici\n");
presence_boucle = d_vrai;
drapeau_boucle_definie = d_faux;
}

printf("<%s> %d\n", (*l_element_pile_systeme).type_cloture, presence_boucle);
l_element_pile_systeme = (*l_element_pile_systeme).suivant;
printf("<> %d\n", presence_boucle);
}

printf("Paf\n");

l_element_pile_systeme est un pointeur sur une structure de liste
chaînée qui contient au moins un champ 'suivant' et un champ statique
(char[6]) type_cloture. Je veux simplement que si la variable
entière presence_boucle devient vrai et qu'on n'est pas encore à la fin
de la liste chaîne, on sorte de la boucle.

Ce code _fonctionnait_. Il est actuellement compilé avec gcc-4.4 -O3
(mais je viens de tester -03 et gcc-4.3). Je ne sais plus avec quelle
configuration ça fonctionnait et je ne vois pas ce que j'aurais changé
depuis...

À l'exécution, ça donne :

>0
Boucle 0
<IF> 0
<> 0
>0
Boucle 0
Ici
<WHILE> 255
<> 255
>255
>0 <-- Je ne comprends pas ÇA...
Boucle 0
<> 0
<> 0
>0
Boucle 0
<> 0
<> 0
Paf

Si quelqu'un avait une idée... Parce que je sèche sur un bout de
code carrément simple et j'ai _honte_...

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.

10 réponses

1 2 3
Avatar
-ed-
On 17 oct, 22:30, JKB wrote:
        J'ai rajouté un printf() pour voir. Le programme origin el n'a aucun
        de ces printf().

        Pour l'instant, je me dirige vers la rédaction d'un rap port de bug
        du compilo et de l'exemple minimal qui va bien... Le truc fonctionne
        parfaitement bien avec Sun Studio et des vieux gcc.




J'aimerais bien savoir dans quelles conditions tu testes exactement.

Ton code est incomplet.

J'ai reconstruit un environnement de test. :

#include <stdio.h>
#include <string.h>

typedef enum
{ d_faux, d_vrai }
bool_e;

typedef struct element_pile_systeme
{
char const type_cloture[6];

struct element_pile_systeme *suivant;
}
element_pile_systeme_s;

typedef struct
{
element_pile_systeme_s *l_base_pile_systeme;
}
etat_processus_s;

void test (etat_processus_s * s_etat_processus)
{
/*
* Test de la présence de l'instruction EXIT dans une boucle
*/

element_pile_systeme_s *l_element_pile_systeme =
s_etat_processus->l_base_pile_systeme;
bool_e presence_boucle = d_faux;
bool_e drapeau_boucle_definie = d_faux;

while ((l_element_pile_systeme != NULL) &&
(printf (">%dn", presence_boucle), presence_boucle ==
d_faux))
{
printf ("Boucle %dn", presence_boucle);
if ((strcmp (l_element_pile_systeme->type_cloture, "START") ==
0) ||
(strcmp (l_element_pile_systeme->type_cloture, "FOR") == 0))
{
printf ("Làn");
presence_boucle = d_vrai;
drapeau_boucle_definie = d_vrai;
}
else if ((strcmp (l_element_pile_systeme->type_cloture, "DO") ==
0) ||
(strcmp (l_element_pile_systeme->type_cloture, "WHILE")
== 0))
{
printf ("Icin");
presence_boucle = d_vrai;
drapeau_boucle_definie = d_faux;
}

printf ("<%s> %dn", l_element_pile_systeme->type_cloture,
presence_boucle);
l_element_pile_systeme = l_element_pile_systeme->suivant;
printf ("<> %dn", presence_boucle);
}

printf ("Pafn");
}

int main (void)
{

static element_pile_systeme_s a[] = {
{"START", a + 1},
{"STOP", NULL},
};

etat_processus_s etat_processus = { a };

test (&etat_processus);

return 0;
}

Peux-tu le compléter pour qu'on soit dans les même conditions que
toi ?
Avatar
JKB
Le 18-10-2009, ? propos de
Re: Problème bizarre,
-ed- ?crivait dans fr.comp.lang.c :
On 17 oct, 22:30, JKB wrote:
        J'ai rajouté un printf() pour voir. Le programme originel n'a aucun
        de ces printf().

        Pour l'instant, je me dirige vers la rédaction d'un rapport de bug
        du compilo et de l'exemple minimal qui va bien... Le truc fonctionne
        parfaitement bien avec Sun Studio et des vieux gcc.




J'aimerais bien savoir dans quelles conditions tu testes exactement.

Ton code est incomplet.

J'ai reconstruit un environnement de test. :

#include <stdio.h>
#include <string.h>

typedef enum
{ d_faux, d_vrai }
bool_e;

typedef struct element_pile_systeme
{
char const type_cloture[6];

struct element_pile_systeme *suivant;
}
element_pile_systeme_s;

typedef struct
{
element_pile_systeme_s *l_base_pile_systeme;
}
etat_processus_s;

void test (etat_processus_s * s_etat_processus)
{
/*
* Test de la présence de l'instruction EXIT dans une boucle
*/

element_pile_systeme_s *l_element_pile_systeme > s_etat_processus->l_base_pile_systeme;
bool_e presence_boucle = d_faux;
bool_e drapeau_boucle_definie = d_faux;

while ((l_element_pile_systeme != NULL) &&
(printf (">%dn", presence_boucle), presence_boucle = > d_faux))
{
printf ("Boucle %dn", presence_boucle);
if ((strcmp (l_element_pile_systeme->type_cloture, "START") = > 0) ||
(strcmp (l_element_pile_systeme->type_cloture, "FOR") == 0))
{
printf ("Làn");
presence_boucle = d_vrai;
drapeau_boucle_definie = d_vrai;
}
else if ((strcmp (l_element_pile_systeme->type_cloture, "DO") = > 0) ||
(strcmp (l_element_pile_systeme->type_cloture, "WHILE")
== 0))
{
printf ("Icin");
presence_boucle = d_vrai;
drapeau_boucle_definie = d_faux;
}

printf ("<%s> %dn", l_element_pile_systeme->type_cloture,
presence_boucle);
l_element_pile_systeme = l_element_pile_systeme->suivant;
printf ("<> %dn", presence_boucle);
}

printf ("Pafn");
}

int main (void)
{

static element_pile_systeme_s a[] = {
{"START", a + 1},
{"STOP", NULL},
};

etat_processus_s etat_processus = { a };

test (&etat_processus);

return 0;
}

Peux-tu le compléter pour qu'on soit dans les même conditions que
toi ?



C'est difficile à faire. Je te remercie pour le temps passé, mais je
suis en train d'essayer d'avoir un exemple minimal qui donne un
résultat faut lors de la compilation. Si je prends la seule routine
fautive (instruction_exit dans mon cas) et que j'isole cette routine
dans un fichier source séparé, elle est correctement compilée. Si je
la mets telle quelle dans le fichier originel, la boucle est mal
compilée. Ça dépasse donc le propos du forum et ça sent l'effet de
bord quelque part dans gcc. Par contre, contrairement à ce que je
disais plus haut (à moins que ce soit sur les listes de diffusion de
gcc, je ne sais plus), ça compile correctement en -O2 et pas en -O3.
Reste à isoler l'option d'optimisation fautive et à trouver un
exemple minimal. J'en suis à bissecter les options de gcc entre -O2
et -O3 ;-)

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Avatar
michko
Eh bien, je vois tout de meme dans ton code un certain nombre
d'affectations, et donc...
Pour ma part, j'ai peine a croire a un bug de gcc dans un tel code et
comme concernant
un programme, je suis comme saint-thomas, et je prefererai que tu
nous donnes le resultat
de la compilation avec gcc -g -Wall suivi de l'output de valgrind.
Plutot que des printf
a droite/a gauche dans ton code, une session gdb avec des displays et
whatis bien choisis
pour nous informer sur la nature des variables mises en jeux. Enfin,
c'est un peu desagreable
de voir des sessions gdb qui ne correspondent pas aux sources !
Choisant une ( l'originale ?),
et ne change plus.

PL

On 17 oct, 11:21, JKB wrote:
Le 17-10-2009, ? propos de
Re: Problème bizarre,
 michko ?crivait dans fr.comp.lang.c :

> Sans doute un pb memoire, plutot que gdb, utilise
> un outil comme valgrind, ou bien donne un code

        J'ai utilisé un valgrind qui n'a _rien_ trouvé. De to ute façon, je
        ne vois pas comment avoir une corruption mémoire dans c e bout de
        code, les seules variables touchées sont les deux drape aux. Le reste
        n'est accédé qu'en lecture et il n'y a aucun thread p arallèle qui
        pourrait modifier cette variable dans mon dos.

> complet. Par ailleurs, ton test sur printf me semble
> un peu superflu...

        C'est simplement pour voir la valeur du drapeau _avant_ l e test.

        Le souci, c'est que ça fonctionne parfaitement sous gdb en pas à pas.
Si je l'exécute sous gdb sans passer sur la fonction en question en pas à pas,
le truc plante de la même façon qu'en exécution normale :

(gdb) run -scp recherche_adresse.rpl
Starting program: /usr/local/bin/rpl -scp recherche_adresse.rpl
[Thread debugging using libthread_db enabled]
+++RPL/2 (R) version 4.0.7 (vendredi 16/10/2009, 22:11:12 CEST)
+++Copyright (C) 1989 à 2008, 2009 BERTRAND Joël>2<

Boucle 0
<IF> 0
<> 0
Boucle 0
Ici
<WHILE> 255
<> 255
Boucle 0
<> 0
<> 0
Boucle 0
<> 0
<> 0
Paf
+++Erreur : Instruction 'EXIT' hors d'une boucle [19895]

Program exited with code 01.
(gdb) break instruction_exit
(gdb) run -scp recherche_adresse.rpl
Starting program: /usr/local/bin/rpl -scp recherche_adresse.rpl
[Thread debugging using libthread_db enabled]
+++RPL/2 (R) version 4.0.7 (vendredi 16/10/2009, 22:11:12 CEST)
+++Copyright (C) 1989 à 2008, 2009 BERTRAND Joël

Breakpoint 1, instruction_exit (s_etat_processus=0xab7b10)
    at instructions_e2.conv.c:1179
warning: Source file is more recent than executable.
1179    {
(gdb) cont
Continuing.

Breakpoin 1, instruction_exit (s_etat_processus=0xab7b10)
    at instructions_e2.conv.c:1179
1179    {
(gdb) cont
Continuing.

>2<

Breakpoint 1, instruction_exit (s_etat_processus=0xab7b10)
    at instructions_e2.conv.c:1179
1179    {
(gdb) next
1195        (*s_etat_processus).erreur_execution = d_ex;
(gdb) next
1197        if ((*s_etat_processus).affichage_arguments == 'Y ')
(gdb) next
1240        else if ((*s_etat_processus).test_instruction == 'Y')
(gdb) next
1250        l_element_pile_systeme =
(*s_etat_processus).l_base_pile_systeme;
(gdb) next
1254        while((l_element_pile_systeme != NULL) && (presence _boucle
== d_faux))
1257            if ((strcmp((*l_element_pile_systeme).type_cl oture,
"START") == 0) ||
(gdb) next
1265                    (strcmp((*l_element_pile_syst eme).type_cloture,
"WHILE") == 0))
(gdb) next
1256    printf("Boucle %dn", presence_boucle);
1257            if ((strcmp((*l_element_pile_systeme).type_cl oture,
"START") == 0) ||
(gdb) next
1256    printf("Boucle %dn", presence_boucle);
(gdb) next
Boucle 0
1257            if ((strcmp((*l_element_pile_systeme).type_cl oture,
"START") == 0) ||
1258                    (strcmp((*l_element_pile_syst eme).type_cloture,
"FOR") == 0))
(gdb) next
1264            else if ((strcmp((*l_element_pile_systeme).ty pe_cloture,
"DO") == 0) ||
(gdb) next
1265                    (strcmp((*l_element_pile_syst eme).type_cloture,
"WHILE") == 0))
1264            else if ((strcmp((*l_element_pile_systeme).ty pe_cloture,
"DO") == 0) ||
(gdb) next
1272    printf("<%s> %dn", (*l_element_pile_systeme).type_cloture,
presence_boucle);
...
(gdb) next
1265                    (strcmp((*l_element_pile_syst eme).type_cloture,
"WHILE") == 0))
(gdb) next
1264            else if ((strcmp((*l_element_pile_systeme).ty pe_cloture,
"DO") == 0) ||
(gdb) next
1267    printf("Icin");
(gdb) next
Ici
1272    printf("<%s> %dn", (*l_element_pile_systeme).type_cloture,
presence_boucle);
(gdb) next
<WHILE> 255
1274    printf("<> %dn", presence_boucle);
(gdb) next
<> 255
1284        if ((*s_etat_processus).mode_execution_programme = = 'Y')
(gdb)

        Je suis sorti normalement de la boucle...

        JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2 % de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.


Avatar
JKB
Le 19-10-2009, ? propos de
Re: Problème bizarre,
michko ?crivait dans fr.comp.lang.c :
Eh bien, je vois tout de meme dans ton code un certain nombre
d'affectations, et donc...
Pour ma part, j'ai peine a croire a un bug de gcc dans un tel code et
comme concernant
un programme, je suis comme saint-thomas, et je prefererai que tu
nous donnes le resultat
de la compilation avec gcc -g -Wall suivi de l'output de valgrind.
Plutot que des printf



Bloc testé :

while((l_element_pile_systeme != NULL) && (presence_boucle == d_faux))
{
if ((strcmp((*l_element_pile_systeme).type_cloture, "START") == 0) ||
(strcmp((*l_element_pile_systeme).type_cloture, "FOR") == 0))
{
presence_boucle = d_vrai;
drapeau_boucle_definie = d_vrai;
}
else if ((strcmp((*l_element_pile_systeme).type_cloture, "DO") == 0) ||
(strcmp((*l_element_pile_systeme).type_cloture, "WHILE") == 0))
{
presence_boucle = d_vrai;
drapeau_boucle_definie = d_faux;
}

l_element_pile_systeme = (*l_element_pile_systeme).suivant;
}

cauchy:[~/rpl/build/src] > gcc -Wall -Dd_date_en_rpl=""Monday 10/19/09,
09:23:18 CEST"" -g -Dd_locale="UTF-8" -DLinux -I.
-I../../rpl-4.0.7/src -I.. -I../../rpl-4.0.7/src -I..
-I../../rpl-4.0.7/tools/readline-6.0 -I../tools/readline-6.0
-DREADLINE_LIBRARY -I../tools/ncurses-5.7/include
-I../../rpl-4.0.7/tools/ncurses-5.7/include -I../tools/gsl-1.13
-I../tools/libiconv-1.13.1/include -I/usr/include/mysql
-I/usr/include/postgresql -DLIBRPL -D_REENTRANT -g
instructions_e2.conv.c -c -DHAVE_CONFIG_H -Dd_version_rpl="4.0.7"
-Dd_exec_path="/usr/local" -DFORCE_GNUPLOT_PATH -UDEBUG
-DMOTIF_SUPPORT -DPOSTSCRIPT_SUPPORT -DGNUPLOT_SUPPORT -DVIM_SUPPORT
-DMYSQL_SUPPORT -DPOSTGRESQL_SUPPORT -UEXPERIMENTAL_CODE
-Dd_date_rpl=""lundi 19/10/2009, 09:23:18 CEST"" -Wno-pointer-sign
cauchy:[~/rpl/build/src] >

Le -Wno-pointer-sign est là pour éviter les warning du type
"warning: pointer targets in passing argument 1 of ‘strcmp’ differ in
signedness" parce qu'ai une bibliothèque qui utilise des (unsigned
char) à la place de (char).

a droite/a gauche dans ton code, une session gdb avec des displays et
whatis bien choisis
pour nous informer sur la nature des variables mises en jeux. Enfin,
c'est un peu desagreable
de voir des sessions gdb qui ne correspondent pas aux sources !
Choisant une ( l'originale ?),



Sortie valgrind de l'original (les '...' indiquent du verbiage
inhérent à mon script et non des sorties valgrind).

cauchy:[~/cartographie] > valgrind --leak-check=full ./recherche_adresse.rpl
= 461== Memcheck, a memory error detector
= 461== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
= 461== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for
copyright info
= 461== Command: ./recherche_adresse.rpl
= 461==
+++RPL/2 (R) version 4.0.7 (lundi 19/10/2009, 09:32:10 CEST)
+++Copyright (C) 1989 à 2008, 2009 BERTRAND Joël
= 461== Syscall param rt_sigaction(act->sa_mask) points to
uninitialised byte(s)
= 461== at 0x61BC824: __libc_sigaction (sigaction.c:65)
= 461== by 0x51731A: rplinit (rpl.conv.c:274)
= 461== by 0x524BAA: main (init.conv.c:29)
= 461== Address 0x7feff5a38 is on thread 1's stack

-> provient de l'appel système sigaction() [fonctionnement normal]

Routine de géolocatisation d'adresses

= 461== Invalid write of size 8
= 461== at 0x843F88F: AES_cbc_encrypt (in /usr/lib/libcrypto.so.0.9.8)
= 461== by 0x3: ???
= 461== Address 0x7feff4a40 is not stack'd, malloc'd or (recently) free'd
= 461==
= 461== Invalid write of size 8
= 461== at 0x843F88F: AES_cbc_encrypt (in /usr/lib/libcrypto.so.0.9.8)
= 461== Address 0x7feff4380 is not stack'd, malloc'd or (recently) free'd
= 461==

-> provient de la libpq5 (je peux virer la libpq5 en mettant la ligne en
commentaire dans mon script, ça vire l'erreur mais ne change rien au
résultat).

Jaro-Winkler library V1R1 for RPL/2 (C) 2009 BERTRAND Joel
Library successfully loaded.

...

+++Erreur : Instruction 'EXIT' hors d'une boucle [20461]
= 461==
= 461== HEAP SUMMARY:
= 461== in use at exit: 66,820 bytes in 2,160 blocks
= 461== total heap usage: 21,519 allocs, 19,359 frees, 2,082,399
bytes allocated
= 461==
= 461== 300 (60 direct, 240 indirect) bytes in 1 blocks are definitely
lost in loss record 182 of 223
= 461== at 0x4C221A7: malloc (vg_replace_malloc.c:195)
= 461== by 0x703842A: nss_parse_service_list (nsswitch.c:618)
= 461== by 0x7038B9E: __nss_database_lookup (nsswitch.c:164)
= 461== by 0xB0302FF: ???
= 461== by 0xB030FAC: ???
= 461== by 0x6FF9821: getpwuid_r@@GLIBC_2.2.5 (getXXbyYY_r.c:253)
= 461== by 0x5FA3E38: ??? (in /usr/lib/libpq.so.5.2)
= 461== by 0x5F8EDA1: ??? (in /usr/lib/libpq.so.5.2)
= 461== by 0x5F913A2: ??? (in /usr/lib/libpq.so.5.2)
= 461== by 0x5F9330C: ??? (in /usr/lib/libpq.so.5.2)
= 461== by 0x5F93CA6: PQsetdbLogin (in /usr/lib/libpq.so.5.2)
= 461== by 0x51EA05: parametres_sql (sql.conv.c:287)

-> Fuite dans la libpq5 (déjà remontée aux devs).

= 461==
= 461== LEAK SUMMARY:
= 461== definitely lost: 60 bytes in 1 blocks
= 461== indirectly lost: 240 bytes in 10 blocks
= 461== possibly lost: 0 bytes in 0 blocks
= 461== still reachable: 66,520 bytes in 2,149 blocks
= 461== suppressed: 0 bytes in 0 blocks
= 461== Reachable blocks (those to which a pointer was found) are not shown.
= 461== To see them, rerun with: --leak-check=full --show-reachable=yes
= 461==
= 461== For counts of detected and suppressed errors, rerun with: -v
= 461== Use --track-origins=yes to see where uninitialised values come from
= 461== ERROR SUMMARY: 403 errors from 15 contexts (suppressed: 10 from 10)
cauchy:[~/cartographie] > gcc -v
Using built-in specs.
Target: sparc-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.4-5'
--with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
--enable-shared --enable-multiarch --enable-linker-build-id
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --enable-nls
--with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3
--enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc
--enable-mpfr --with-cpu=v8 --with-long-double-128
--enable-checking=release --build=sparc-linux-gnu --host=sparc-linux-gnu
--target=sparc-linux-gnu
Thread model: posix
gcc version 4.3.4 (Debian 4.3.4-5)
cauchy:[~/cartographie] >

J'ai testé la même chose avec un 4.4.1 d'origine debian. Même motif,
même punition.

Hier soir, j'en étais resté à bissecter les options d'optimisations
pour la compilation du code, sans résultat. Par contre, au vu du
nombre de problèmes corrigés dans gcc récemment, j'ai profité de la
nuit pour pour bootstraper un gcc-4.4.2 complet depuis les
sources sur la même machine (sparc64). Avec les mêmes options de
compilation, ça compile et fonctionne parfaitement.

Preuve :
cauchy:[~/cartographie] > valgrind --leak-check=full ./recherche_adresse.rpl
=$614== Memcheck, a memory error detector
=$614== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
=$614== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for
copyright info
=$614== Command: ./recherche_adresse.rpl
=$614==
+++RPL/2 (R) version 4.0.7 (lundi 19/10/2009, 09:43:07 CEST)
+++Copyright (C) 1989 à 2008, 2009 BERTRAND Joël
=$614== Syscall param rt_sigaction(act->sa_mask) points to
uninitialised byte(s)
=$614== at 0x61BC824: __libc_sigaction (sigaction.c:65)
=$614== by 0x518254: rplinit (rpl.conv.c:1393)
=$614== by 0x524C0A: main (init.conv.c:29)
=$614== Address 0x7feff5a38 is on thread 1's stack
=$614==
...
Routine de géolocatisation d'adresses

=$614== Invalid write of size 8
=$614== at 0x843F88F: AES_cbc_encrypt (in /usr/lib/libcrypto.so.0.9.8)
=$614== by 0x3: ???
=$614== Address 0x7feff4a40 is not stack'd, malloc'd or (recently) free'd
...
Jaro-Winkler library V1R1 for RPL/2 (C) 2009 BERTRAND Joel
Library successfully loaded.
...
Bureau distributeur : PESMES
Cedex :
Pays :
Code INSEE : 70444

Jaro-Winkler library unloaded.

=$614==
=$614== HEAP SUMMARY:
=$614== in use at exit: 66,820 bytes in 2,160 blocks
=$614== total heap usage: 22,689 allocs, 20,529 frees, 2,170,510
bytes allocated
=$614==
=$614== 300 (60 direct, 240 indirect) bytes in 1 blocks are definitely
lost in loss record 182 of 223
=$614== at 0x4C221A7: malloc (vg_replace_malloc.c:195)
=$614== by 0x703842A: nss_parse_service_list (nsswitch.c:618)
=$614== by 0x7038B9E: __nss_database_lookup (nsswitch.c:164)
=$614== by 0xB0302FF: ???
=$614== by 0xB030FAC: ???
=$614== by 0x6FF9821: getpwuid_r@@GLIBC_2.2.5 (getXXbyYY_r.c:253)
=$614== by 0x5FA3E38: ??? (in /usr/lib/libpq.so.5.2)
=$614== by 0x5F8EDA1: ??? (in /usr/lib/libpq.so.5.2)
=$614== by 0x5F913A2: ??? (in /usr/lib/libpq.so.5.2)
=$614== by 0x5F9330C: ??? (in /usr/lib/libpq.so.5.2)
=$614== by 0x5F93CA6: PQsetdbLogin (in /usr/lib/libpq.so.5.2)
=$614== by 0x51EA65: parametres_sql (sql.conv.c:287)
=$614==
=$614== LEAK SUMMARY:
=$614== definitely lost: 60 bytes in 1 blocks
=$614== indirectly lost: 240 bytes in 10 blocks
=$614== possibly lost: 0 bytes in 0 blocks
=$614== still reachable: 66,520 bytes in 2,149 blocks
=$614== suppressed: 0 bytes in 0 blocks
=$614== Reachable blocks (those to which a pointer was found) are not shown.
=$614== To see them, rerun with: --leak-check=full
--show-reachable=yes
=$614==
=$614== For counts of detected and suppressed errors, rerun with: -v
=$614== Use --track-origins=yes to see where uninitialised values come from
=$614== ERROR SUMMARY: 1723 errors from 15 contexts (suppressed: 10 from 10)
cauchy:[~/cartographie] >

En dehors d'un bug sournois dans gcc provoqué par quelque chose
écrit bien avant dans le même fichier source, je ne vois pas.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Avatar
Senhon
"JKB" a écrit dans le message de groupe de
discussion :
Le 19-10-2009, ? propos de

En dehors d'un bug sournois dans gcc provoqué par quelque chose
écrit bien avant dans le même fichier source, je ne vois pas.



Ne m'en veut pas : mais, comme ça juste à l'intuition et par expérience,
dire que GCC buggue, avec juste pour preuve un extrait de code simplissime,
qui ne compile pas tel quel, me parait un peu ... anticipé comme
constatation.
C'est typique d'un programme qui tombe en marche.

Sauf si tu présente un code exploitable et reproduisant le défaut, il est
fort à parier que l'erreur provient de ton application.
Avatar
JKB
Le 19-10-2009, ? propos de
Re: Problème bizarre,
Senhon ?crivait dans fr.comp.lang.c :

"JKB" a écrit dans le message de groupe de
discussion :
Le 19-10-2009, ? propos de

En dehors d'un bug sournois dans gcc provoqué par quelque chose
écrit bien avant dans le même fichier source, je ne vois pas.



Ne m'en veut pas : mais, comme ça juste à l'intuition et par expérience,
dire que GCC buggue, avec juste pour preuve un extrait de code simplissime,
qui ne compile pas tel quel, me parait un peu ... anticipé comme
constatation.
C'est typique d'un programme qui tombe en marche.



Mais je n'en veut à personne... Le fait est que ce bout de code
tournait depuis des années, que j'ai recompilé avec un compilo plus
récent pour une modification mineure (une coquille dans un prinf) et
que je me suis aperçu que ça ne fonctionnait plus. Avant de mettre
en cause le compilo, j'ai cherché, j'ai utilisé des trucs comme
valgrind et d'autres ruses plus sioux car depuis que j'utilise des
compilo, je n'avais trouvé qu'un bug dans le 2.7.2.3 sous
Solaris/sparc32 (ça ne nous rajeunit pas !) et un autre truc amusant
dans le très vieux Turbo Basic de Borland. Pour être honnête, je
pensais à un débordement quelque part (bien que je ne me l'expliquais
pas parce qu'il n'y a aucune raison qu'une telle variable change
dans le dos du programme qui ne fait rien d'autre). J'ai bien entendu
commencé par mettre mon code en doute. Je n'ai pas non plus
l'habitude de pousser les compilos dans leurs retranchements.

Sauf si tu présente un code exploitable et reproduisant le défaut, il est
fort à parier que l'erreur provient de ton application.



Ce qui m'a fait mettre le comportement de gcc en doute, ce sont deux
choses. Dans un premier temps : j'ai coupé le fichier en question en deux.
D'un côté la fonction dans laquelle la boucle en question se situe, de
l'autre le reste du .c fautif. Le code source n'a donc pas changé.
Avec le même compilo et les mêmes options de compilation, ça fonctionne.
Je pense que si mon code avait un problème (ce que note bien j'accepterai,
ce n'est pas parce que je fais du C depuis vingt ans que je n'écris
pas de conn^Wbêtises ...), il aurait exactement le même problème dans
le cas d'un autre découpage des fichiers sources.

La deuxième chose est une analyse à la main du code assembleur qui
fait que dans le cas où la compilation n'est pas bonne, le code
généré est conforme à un source qui serait du type :

while((l_element_pile_systeme != NULL) && (presence_boucle = d_faux))
{
}

avec une égalité et non un test. En fait, avec l'option -O3, ces
deux variables sont dans des registres et non en mémoire et c'est là
qu'il y a un problème. Le premier test est effectué, mais le second
test est, dans le cas où apparaît le problème, une comparaison à
zéro pure et dure d'un registre réinitialisé à 0 lors du retour
de la boucle. Si la variable presence_boucle est écrite en
mémoire, le problème ne se pose plus. Si j'isole cette fonction dans
un autre fichier source, ça ne se produit pas non plus.

Le fait que gcc-4.2 compile correctement (ainsi que Sun Studio) me
font aussi pencher pour un obscur problème de certaines versions de
gcc. On m'a d'ailleurs toujours dit de me méfier de l'option -O3 de
gcc...

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Avatar
Senhon
"JKB" a écrit dans le message de groupe de
discussion :

Ce qui m'a fait mettre le comportement de gcc en doute, ce sont deux
choses. Dans un premier temps : j'ai coupé le fichier en question en deux.
D'un côté la fonction dans laquelle la boucle en question se situe, de
l'autre le reste du .c fautif. Le code source n'a donc pas changé.
Avec le même compilo et les mêmes options de compilation, ça fonctionne.
Je pense que si mon code avait un problème (ce que note bien j'accepterai,
ce n'est pas parce que je fais du C depuis vingt ans que je n'écris
pas de conn^Wbêtises ...), il aurait exactement le même problème dans
le cas d'un autre découpage des fichiers sources.



Tu as raison, y a de quoi être surpris.
Avatar
-ed-
On 19 oct, 15:57, JKB wrote:
        Mais je n'en veut à personne... Le fait est que ce bout de code
        tournait depuis des années, que j'ai recompilé avec u n compilo plus



Mais ça ne prouve pas qu'il soit exempt de bug, notamment de
comportement indéfini...

        while((l_element_pile_systeme != NULL) && (presence_bou cle = d_faux))
        {
        }

        avec une égalité et non un test. En fait, avec l'opti on -O3, ces



C'est quoi une égalité ? Tu veux dire une affectation ?
(presence_boucle = d_faux).

En 20 ans de C, tu ne connais pas encore les termes corrects ?

Tu sous entend que dès qu'un des termes de l'expression (en partant de
la gauche) avec des && vait 0, les autres de sont pas évalués. C'est
certainement vrai pour des expression pures (comparaisons),

par exemple, le très classique : while (p != NULL && *p != 0) p++;

mais pas sûr que ce soit vrai si il y a des affectations dans
l'expression... Il est possible que ça dépende de l'implémentation,
d'où un changement de comportement quand tu changes de compilateur.
Avatar
JKB
Le 19-10-2009, ? propos de
Re: Problème bizarre,
-ed- ?crivait dans fr.comp.lang.c :
On 19 oct, 15:57, JKB wrote:
        Mais je n'en veut à personne... Le fait est que ce bout de code
        tournait depuis des années, que j'ai recompilé avec un compilo plus



Mais ça ne prouve pas qu'il soit exempt de bug, notamment de
comportement indéfini...



Nous sommes bien d'accord. Mais ce comportement indéfini comme tu
dis (encore que je les chasse) serait le _même_ que cette fonction
soit seule dans un fichier .c ou avec d'autres.

        while((l_element_pile_systeme != NULL) && (presence_boucle = d_faux))
        {
        }

        avec une égalité et non un test. En fait, avec l'option -O3, ces



C'est quoi une égalité ? Tu veux dire une affectation ?
(presence_boucle = d_faux).

En 20 ans de C, tu ne connais pas encore les termes corrects ?



Si, et c'est exactement le mot que je cherchais tout à l'heure.

Tu sous entend que dès qu'un des termes de l'expression (en partant de
la gauche) avec des && vait 0, les autres de sont pas évalués. C'est
certainement vrai pour des expression pures (comparaisons),

par exemple, le très classique : while (p != NULL && *p != 0) p++;

mais pas sûr que ce soit vrai si il y a des affectations dans
l'expression... Il est possible que ça dépende de l'implémentation,
d'où un changement de comportement quand tu changes de compilateur.



Il n'y a _aucune_ affectation dans l'expression, rien du tout. Le
compilo génère un code assembleur dans certains cas avec
certaines options de compilation qui proviendrait plus de

while((l_element_pile_systeme != NULL) && (presence_boucle = d_faux))

que de

while((l_element_pile_systeme != NULL) && (presence_boucle == d_faux))

qui est ce qui est désiré. Le fait est qu'avec gcc-4.4.2, le code
_assembleur_ est correct alors qu'avec des gcc plus anciens, le code
généré est erroné (au moins sur sparc). Je parle de code _assembleur_
de la boucle, pas de comportements indéfinis en C. D'ailleurs, dans la
ligne en question, je me demande bien où il pourrait y avoir un comportement
indéfini. L'erreur est _simple_, le registre L0 utilisé pour stocker la
variable locale presence_boucle est réinitialisé juste après le saut
depuis la fin du bloc et avant le test. C'est certainement un
problème de calcul d'adresse de retour dans certaines conditions,
mais je n'ai pas le temps de creuser plus. J'aurais creusé bien plus
loin si le truc n'avait pas été corrigé dans la dernière mouture.

Je vais donc clore la discussion qui est plus un problème de compilo
qu'un problème de C.

Merci à ceux qui ont essayé de m'aider.

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Avatar
-ed-
On 19 oct, 17:55, JKB wrote:
> mais pas sûr que ce soit vrai si il y a des affectations dans
> l'expression... Il est possible que ça dépende de l'implémentatio n,
> d'où un changement de comportement quand tu changes de compilateur.

        Il n'y a _aucune_ affectation dans l'expression, rien du tout. Le
        compilo génère un code assembleur dans certains cas a vec
        certaines options de compilation qui proviendrait plus de

        while((l_element_pile_systeme != NULL) && (presence_bou cle = d_faux))



Ici, il y a clairement une affectation. Tu veux dire que le code
généré correspond à celui-ci


        que de

        while((l_element_pile_systeme != NULL) && (presence_bou cle == d_faux))



alors que tu as codé cela ?

Si c'est le cas, oui, c'est un bug du compilateur.

        Je vais donc clore la discussion qui est plus un problè me de compilo
        qu'un problème de C.



OK.
1 2 3