IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Floating point exception sous linux


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Par défaut Floating point exception sous linux
    Bonjour,
    Je cherche a savoir comment on récupère l'exception lorsque on lève un signal 8 SIGFPE sous linux. Mon but est simple, si je fais un OVERFLOW, un UNDERFLOW, un INVALID ou un DIVBYZERO(float) alors j'affiche une trace du style : "blabla signal(8) SIGFPE de type INVALID blabla".

    Dans l'idée, je cherche à avoir la même information que donne la fonction GetExceptionCode sous Windows
    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
    (mais juste les 4 que j'ai cité au dessus)
    J'ai bien regardé dans "fenv.h", mais à part la fonction int fegetexceptflag(fexcept_t *pflag, int except); dont je ne sais pas m'en servir j'ai rien trouvé d'autre.

    Merci d'avance pour vos réponses.

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Salut,

    Le fait est que ce genre d'erreur n'est absolument pas une exception dans le sens C++ du terme, mais bien un signal d'erreur émit de "bien plus bas"

    Lorsque tu obtiens ce genre de signal, c'est, sans doute, parce que tu n'as pas pris assez de précaution avant d'effectuer ton calcul (par exemple, que tu n'a pas vérifié que le dénominateur d'une division était différent de 0).

    C'est en effet dans la même lignée que le fameux SIGSEGV qui indique une erreur de segmentation (une tentative d'accès indue à une adresse mémoire )

    Plutôt que d'essayer de récupérer le signal d'erreur, il semble bien plus utile d'essayer de faire en sorte qu'elle n'arrive pas

    Ceci dit, en Ansi C, tu devrais pouvoir utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void (*signal(int sig, void (*action)(int)))(int);
    pour définir un gestionnaire sur un signal donné.

    Il s'agit donc, pour te permettre de comprendre, de l'utilisation de deux pointeurs de fonctions :

    Le premier (qui "récupère" le signal) est void (*signal(int sig, autrePointeur)(int) ou sig est le numéro du signal à attraper et ou autre pointeur est un pointeur sur la fonction qui devra le gérer ( pour etre précis, un pointeur sur fonction de type void(*action)(int) )

    Il n'y a, à ma connaissance du moins (mais je peux me tromper sur ce coup là ) d'équivalence en C++
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Salut

    Des fonctionnalités de gestion des "exceptions" (qui ne sont effectivement pas des exceptions au sens du C++, càd qui se gèrent avec throw/catch) ont été ajoutée dans le C++11 : Floating-point environment. Tu as des codes d'exemple dans les pages des fonctions.

    Par contre, je ne sais pas quels compilateurs implémentent ça.

    Dans gcc, tu as aussi la libc (donc du C... mais la version C++11 semble être simplement la reprise du code C) qui permet de gérer ça : 20.5.3 Examining the FPU status word (attention à la différence de headers : <cfenv> pour le C++11 et <fenv.h> pour le C)

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Par défaut
    Autant pour moi je regarde de suite. Il n'y a pas plus simple? voici mon test unitaire sous linux uniquement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
     
    #include <sys/resource.h>
    #include <stdio.h>
    #include <math.h>
    #include <float.h>
    #include <iostream>
    #include <string>
    #include <setjmp.h>
    #include <fenv.h>
    #include <signal.h>
     
    using namespace std;
     
    #define try_with_signal_handler if (!sigsetjmp(env, 1))
    #define catch_with_signal_handler else
    static sigjmp_buf env;
     
    void sig_handler(int sig)
    {
      printf (" Application shall not crash on %d \n", sig);
      siglongjmp(env,sig);
    }
     
    void show_status_of_fpe()
    {
      int result_fegetexcept = fegetexcept();
      if(result_fegetexcept&FE_INVALID)
        printf("FE_INVALID\n");
      else if(result_fegetexcept&FE_OVERFLOW)
        printf("FE_OVERFLOW\n");
      else if(result_fegetexcept&FE_UNDERFLOW)
        printf("FE_UNDERFLOW\n");
      else if(result_fegetexcept&FE_DIVBYZERO)
        printf("FE_DIVBYZERO\n");
      else
        printf("NO FPE\n");
    }
     
    void set_signal_on_fpe()
    {
      feenableexcept(FE_DIVBYZERO|FE_UNDERFLOW|FE_OVERFLOW|FE_INVALID); 
      //feenableexcept(FE_INVALID|FE_OVERFLOW); // pour verif si show_status_of_fpe marche
      signal(8, &sig_handler);
    }
     
    int main( void )
    {
      float a=0.0;
      float b=0.0;
      int c=0;
      int d=0; 
     
     
      //NO SIGNAL CATCH
      /*
      try_with_signal_handler
      {  
        printf("-------------------------\n");
        
        printf("Div by zero : ");
        a = 3.0 / b;
        printf("OK : a = %f\n",a);
        
        printf("OVERFLOW : ");
        a = exp(1000);
        printf("OK : a =  %f\n",a);
        
        printf("UNDERFLOW : ");
        a = exp(-1000);
        printf("OK : a =  %f\n",a);
        
        printf("INVALID : ");
        a = sqrt(-1);
        printf("OK : a =  %f\n",a);
        
      }
      catch_with_signal_handler
      {
        printf("Catch fpe exception ...\n");    
      }
      printf("-------------------------\n");  
      */
     
     
      set_signal_on_fpe();   
      printf("Activating signal handling\n");  
     
     
      // DIV BY ZERO FLOAT
     
      printf("-------------------------\n");  
      try_with_signal_handler 
      {     
        printf("Div by zero : ");
        a = 3 / b;
        printf("OK : a =  %f\n",a);
      }
      catch_with_signal_handler
      {
        printf("Catch fpe exception ...\n");
      }
      printf("-------------------------\n");  
     
     
     
      //OVERFLOW
      /*
      printf("-------------------------\n");  
      set_signal_on_fpe();   
      try_with_signal_handler 
      {         
        printf("OVERFLOW : ");
        a = exp(1000);//attention machine 32bit only
        printf("OK : a =  %f\n",a);
      } 
      catch_with_signal_handler
      {
        printf("Catch fpe exception ...\n");    
      }
      printf("-------------------------\n");  
      */
     
     
      // UNDERFLOW
      /*
      printf("-------------------------\n");  
      set_signal_on_fpe();   
      try_with_signal_handler 
      {         
        printf("UNDERFLOW : ");
        a = exp(-1000);//attention machine 32bit only
        printf("OK : a =  %f\n",a);
      } 
      catch_with_signal_handler
      {
        printf("Catch fpe exception ...\n");
      }
      printf("-------------------------\n");  
      */
     
      // INVALID
      /*
      printf("-------------------------\n");  
      set_signal_on_fpe();   
      try_with_signal_handler 
      {         
        printf("INVALID : ");
        a = sqrt(-1);
        printf("OK : a =  %f\n",a);
      } 
      catch_with_signal_handler
      {
        printf("Catch fpe exception ...\n");
      }
      printf("-------------------------\n");
      */
     
      // DIV BY ZERO INT
      /*
      printf("-------------------------\n");  
      try_with_signal_handler 
      {     
        printf("Div by zero int : ");
        c = 3 / d;
        printf("OK : c =  %f\n",c);
      }
      catch_with_signal_handler
      {
        printf("Catch fpe exception ...\n");
      }
      printf("-------------------------\n");  
      */
     
      return 0;  
    }
    Est ce que dans mon catch_with_signal_handler, il n'existe pas une fonction linux qui me permet de dire qu'elle opération de type SIGFPE il s'agit.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Par défaut la solution
    Je reviens pour donner la solution.

    Alors sous windows avec GetExceptionCode, on a toute les informations que l'on veut sur les Floating Point Exception.
    Sous linux il faut faire un sigaction et l'information est contenu dans si_code.

    J'ai trouvé ça dans http://www.linuxprogrammingblog.com/...ples/sigaction

    Voici l'exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
     
    /* Example of using sigaction() to setup a signal handler with 3 arguments
     * including siginfo_t.
     */
    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    #include <string.h>
     
    static void hdl (int sig, siginfo_t *siginfo, void *context)
    {
    	printf ("Sending PID: %ld, UID: %ld\n",
    			(long)siginfo->si_pid, (long)siginfo->si_uid);
    	printf ("Code du FPE: %d\n",siginfo->si_code);
    }
     
    int main (int argc, char *argv[])
    {
    	struct sigaction act;
     
    	memset (&act, '\0', sizeof(act));
     
    	/* Use the sa_sigaction field because the handles has two additional parameters */
    	act.sa_sigaction = &hdl;
     
    	/* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
    	act.sa_flags = SA_SIGINFO;
     
    	if (sigaction(SIGTERM, &act, NULL) < 0) {
    		perror ("sigaction");
    		return 1;
    	}
     
    	while (1)
    		sleep (10);
     
    	return 0;
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [runtime exception] Floating point exception
    Par xion.luhnis dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 17/09/2010, 04h57
  2. Floating Point Exception
    Par étoile de mer dans le forum Débuter
    Réponses: 3
    Dernier message: 28/10/2009, 17h09
  3. Réponses: 1
    Dernier message: 06/05/2009, 16h36
  4. Floating point exception dans dlopen()
    Par Invité dans le forum C++
    Réponses: 0
    Dernier message: 10/06/2008, 09h56
  5. Trace de l exception sous linux et eclipse3.3.2
    Par NizarK dans le forum Eclipse Java
    Réponses: 0
    Dernier message: 25/04/2008, 12h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo