Faire un don ! | | style | statistiques | contactez-nous | plan | lettre d'information

Journal : Le Pourquoi Windows plante !

Posté par Snarky (Jabber id, page perso, ) le 18 août 2007
Voici un soucis que j'ai eu aujourd'hui et qui m'as fait perdre deux bonnes heures de boulot pour RIEN !

Bon, c'est en relation avec Microsoft Windows(c) mais ça prouve bien que même le B-A-BA du fonctionnement d'un logiciel et biaisé par l'OS, et provoque donc des plantages là où ça ne devrai pas.

Alors voici mon problème, je suis en cours de portage d'une de mes applications vers Windows(c)... :-(
Remarquant un bug d'une valeur, je part à la chasse au bug pour finalement isoler le bug suivant :
double a = 800.0 ;
double b = 0.75 ;
double c = 0.6 ;
double d = a*b*c ;
printf("Prend %f * %f * %f = %f ( %i ) = %f ( %i ) %\n", a, b, c, a*b*c, (int)(a*b*c), d, (int)d) ;


Même un développeur de base comprendra ce code.
Et voici le résultat de l'exécution sous Windows (aucun soucis sous linux) :
Prend 800.000000 * 0.750000 * 0.600000 = 360.000000 ( 359 ) = 360.000000 ( 360 )

Peut-t-on m'expliquer ce que fou là ce 359 !? Windows compte mal à ce point ?
Ca m'inquiète sincèrement sur la qualité d'application même bien développé...

Pour information, ça a été compilé avec g++ 3.4.4 sous Windows.


PS: A la base, je voulais poster ça dans le forum de developpez.net (qui est mieux pour les questions dev), mais il est HS. Donc j'ai voulu mettre sur ce forum, qui n'est pas accessible non plus, donc en désespoir de cause, je poste ici :-)

> Lire le journal (49 commentaires, moyenne: 4,1).  

Vous avez demandé le commentaire #860074.

Chez moi...

Posté par pasSteve pasJobs () le 18/08/2007 à 16:44. (lien). Évalué à 10.

steve@myhost ~ $ cat test.c
#include <stdio.h>

int main() {
double a = 800.0 ;
double b = 0.75 ;
double c = 0.6 ;
double d = a*b*c ;
printf("Prend %f * %f * %f = %f ( %i ) = %f ( %i ) %\n",
a, b, c, a*b*c, (int)(a*b*c), d, (int)d) ;
return 0;
}
steve@myhost ~ $ gcc test.c -o test
steve@myhost ~ $ ./test
Prend 800.000000 * 0.750000 * 0.600000 = 360.000000 ( 359 ) = 360.000000 ( 360 ) %
steve@myhost ~ $ llvm-gcc test.c -o test
steve@myhost ~ $ ./test
Prend 800.000000 * 0.750000 * 0.600000 = 360.000000 ( 360 ) = 360.000000 ( 360 ) %
steve@myhost ~ $ icc test.c -o test
steve@myhost ~ $ ./test
Prend 800.000000 * 0.750000 * 0.600000 = 360.000000 ( 360 ) = 360.000000 ( 360 ) %
steve@myhost ~ $ gcc --version
gcc (GCC) 4.2.1
Copyright © 2007 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie. Il n'y a PAS
GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

steve@myhost ~ $ llvm-gcc --version # LLVM 2.0
llvm-gcc (GCC) 4.0.1 (Apple Computer, Inc. build 5449)
Copyright © 2005 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie. Il n'y a PAS
GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

steve@myhost ~ $ icc --version
icc (ICC) 10.0 20070426
Copyright (C) 1985-2007 Intel Corporation. All rights reserved.

  • [^]Re: Chez moi...

    Posté par micha_mosk () le 18/08/2007 à 16:49. (lien). Évalué à 4.

    Je confirme, je viens d'essayer avec gcc 4.1.2 (Ubuntu 4.1.2-0ubuntu4), et j'obtiens la valeur erronée de 359.

    • [^]Re: Chez moi...

      Posté par inico (Jabber id, page perso, ) le 18/08/2007 à 16:59. (lien). Évalué à 3.


      $ tcc -run test.c
      Prend 800.000000 * 0.750000 * 0.600000 = 360.000000 ( 359 ) = 360.000000 ( 360 ) %
      $ tcc -v
      tcc version 0.9.23


      Même chose avec gcc sous Solaris et Windows.
      Je cherche d'autre compilateur pour tester.

      --
      "Les États-Unis sont le seul pays à être passé de la barbarie à la décadence sans connaître la civilisation." -- (origine réelle inconnue) Albert Einstein/Oscar Wilde/Georges Clemenceau/etc..

    [^]Re: Chez moi...

    Posté par Batchyx () le 18/08/2007 à 16:57. (lien). Évalué à 2.

    chez moi tout marche parfaitement bien si je met un -O ...

    [^]Re: Chez moi...

    Posté par Moonz () le 18/08/2007 à 17:05. (lien). Évalué à 3.

    Pareil ici, mais:
    /tmp 19:04 gcc -ffloat-store test.c -o test && ./test
    Prend 800.000000 * 0.750000 * 0.600000 = 360.000000 ( 360 ) = 360.000000 ( 360 ) %

    Ça marche donc avec -ffloat-store qui est activé pour -O1 (ou supérieur) ou -Os. En fait, il n'y a que -O0 qui fout la merde :)

    • [^]Re: Chez moi...

      Posté par Vivi (page perso, ) le 21/08/2007 à 17:03. (lien). Évalué à 1.

      pas du tout, -ffloat-store n'est pas vraiment une option "d'optimisation", ça a plutôt tendance à ralentir le code. Et elle n'est pas automatiquement activée par -O1 et supérieur.

      Le but de cette option est d'empêcher de se trimballer des résultats intermédaires flottants ayant plus de 64 bits de précision. Donc ça rajoute (en gros) des store/load après chaque calcul flottant pour forcer une troncation à 64 bits et assurer un calcul plus conforme à la norme IEEE.

      Le meilleur moyen d'éviter ces problèmes, c'est d'utiliser une plateforme faisant ses calculs flottans en 64bits, donc abandonner le FPU x87. C'est en fait trés facile avec un ordi récent, il suffit d'utiliser le SSE2: option -msse2 -mfpmath=sse pour un x86, rien à faire pour un x86_64.