2010-05-31 8 views

risposta

20

Quasi tutte le operazioni in virgola mobile o la funzione di libreria matematica che produce un NaN da ingressi non NaN devono anche segnalare l'eccezione a virgola mobile "operazione non valida"; analogamente, un calcolo che produce un infinito dagli input finiti di solito segnalerà l'eccezione a virgola mobile "divide per zero" o "overflow". Quindi vuoi un modo per trasformare queste eccezioni in un SIGFPE.

Sospetto che la risposta sia altamente dipendente dal sistema, dal momento che il controllo delle trappole e dei flag in virgola mobile viene probabilmente fornito dalla libreria della piattaforma C anziché da gcc. Ma ecco un esempio che funziona per me, su Linux. Utilizza la funzione feenableexcept da fenv.h. La definizione _GNU_SOURCE è necessaria per dichiarare questa funzione.

#define _GNU_SOURCE 
#include <fenv.h> 

int main(void) { 
    double x, y, z; 
    feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); 

    x = 1e300; 
    y = 1e300; 
    z = x * y; /* should cause an FPE */ 

    return 0; 
} 

Un avvertimento: Penso che sia possibile con alcune impostazioni che l'eccezione non viene effettivamente generato fino a quando l'operazione in virgola mobile prossimo dopo quello che (in teoria) dovrebbe averlo causato, in modo a volte è necessario un funzionamento in virgola mobile non operativo (ad esempio moltiplicando per 1,0) per attivare l'eccezione.

4

Su MinGW 4.8.1 (GCC per Win32) Vedo che lo feenableexcept non è definito. La soluzione è quella di utilizzare la piattaforma Win32 _controlfp così:

#undef __STRICT_ANSI__ // _controlfp is a non-standard function documented in MSDN 
#include <float.h> 
#include <stdio.h> 

int main() 
{ 
    _clearfp(); 
    unsigned unused_current_word = 0; 
    // clearing the bits unmasks (throws) the exception 
    _controlfp_s(&unused_current_word, 0, _EM_OVERFLOW | _EM_ZERODIVIDE); // _controlfp_s is the secure version of _controlfp 

    float num = 1.0f, den = 0.0f; 
    float quo = num/den; 
    printf("%.8f\n", quo); // the control should never reach here, due to the exception thrown above 
} 
+0

Questo non sembra funzionare su MinGW 4.6.2 ('_clearfp()' non è stato dichiarato in questo ambito) – Antonello

Problemi correlati