2010-05-31 10 views
16

¿Hay alguna manera de decirle a gcc que arroje un SIGFPE o algo similar en respuesta a un cálculo que da como resultado NaN o (-)inf en tiempo de ejecución, como lo haría con una división por cero?¿Puedo hacer que gcc me diga cuándo un cálculo da como resultado NaN o inf en tiempo de ejecución?

He intentado con la bandera -fsignaling-nans, lo cual no parece ser de ayuda.

+1

'-fsignaling-nans' es el tiempo de ejecución, no en tiempo de compilación. – LiraNuna

+2

¿En qué sistema estás? –

Respuesta

20

Casi cualquier operación de coma flotante o función de biblioteca matemática que produce un NaN de entradas que no sean NaN también debe señalar la excepción de coma flotante 'operación no válida'; de forma similar, un cálculo que produce un infinito a partir de entradas finitas normalmente indicará la excepción de punto flotante 'dividir por cero' o 'desbordamiento'. Entonces quieres alguna manera de convertir estas excepciones en un SIGFPE.

Sospecho que la respuesta dependerá en gran medida del sistema, ya que el control de las trampas de coma flotante y las banderas es probable que sea suministrado por la biblioteca de la plataforma C en lugar de por la propia gcc. Pero aquí hay un ejemplo que funciona para mí, en Linux. Utiliza la función feenableexcept de fenv.h. La definición _GNU_SOURCE es necesaria para declarar esta función.

#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; 
} 

Una advertencia: Creo que es posible con algunas configuraciones que en realidad no es la excepción generada hasta que la operación de punto flotante siguiente después del que (en teoría) debería haber causado, por lo que a veces necesita una operación de coma flotante no operativa (por ejemplo, multiplicando por 1.0) para activar la excepción.

4

En MinGW 4.8.1 (GCC para Win32) Veo que feenableexcept no está definido. La solución consiste en utilizar la plataforma de Win32 _controlfp así:

#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

Esto no parece funcionar en MinGW 4.6.2 ('_clearfp()' no se declaró en este ámbito) – Antonello

Cuestiones relacionadas