2011-02-02 14 views
9

Me gustaría hacer que la compilación de algunos archivos falle si se intenta después de una fecha determinada. La razón de esto es que encontré un par de errores de Y2K38 que no tengo tiempo de corregir en este momento, pero me gustaría tomar nota de ellos y creo que sería bueno que la compilación del módulo simplemente fallara después, decir, 2020. (que podría ser una locura, pero este código tiene 20 años sospecho que podría sobrevivir a otra 30)preprocesador c: error al compilar después de cierta fecha

+1

¿No es más el problema de que el programa deje de ejecutarse en 2038, no que deje de compilar? –

+8

¿A quién le importa si no puede compilarlo después, digamos, 2020? El problema es si todavía hay una versión compilada en producción en alguna parte en 2038. Arregle esa mierda, pronto, y consiga que se implemente. – jason

+4

¿Has considerado una # advertencia? Las he usado antes como pequeñas cosas para el futuro. – whitey04

Respuesta

5

con gcc, se puede hacer algo como lo siguiente:

void __attribute__((error("Whoa. It's the future"))) whoa_the_future(); 

void check_for_the_future() { 
    // "Feb 1 2011" 
    const char *now = __DATE__; 
    if (now[9] >= '2') 
     whoa_the_future(); 
} 

la forma esto funciona porque el atributo error le dice a GCC que genere un error en tiempo de compilación si quedan llamadas en esa función en el código después de todo el código muerto y plegado constante de GCC eliminación, y pases similares se han ejecutado. Desde FECHA es una constante de tiempo de compilación, GCC puede evaluar la instrucción if en tiempo de compilación y eliminar la llamada .

Al menos una desventaja es que esto depende de la optimización pases de CCG, y por lo tanto no funcionará en gcc -O0

Honestamente, es posible que mejor simplemente añadiendo una comprobación en tiempo de ejecución en algún lugar y no rápido.

+4

Para el 2100, los compiladores arreglarán automáticamente cosas como 2038 errores. – aschepler

+3

@aschepler: esperemos que solucionen automáticamente 2038 errores en 2038. –

+0

@nelhage gracias, esto es interesante. Por supuesto, necesito esto tanto en VS como en gcc :) Tienes razón, el control del tiempo de ejecución es probablemente mejor. –

0

Una solución más genérica que debería funcionar con la mayoría de los compiladores. Depende un poco en el formato de la Directiva FECHA preprocesador

#define DIGIT(ch) (((ch)<'0'||(ch)>'9') ? 0 : ((ch)-'0')) 
#define YEAR (1000*DIGIT(__DATE__[7])+100*DIGIT(__DATE__[8])+10*DIGIT(__DATE__[9])+DIGIT(__DATE__[10])) 

#ifdef YEAR-2020>0 
#error too old 
#endif 
+0

'#ifdef YEAR-2038> 0'? –

+2

La suscripción de matriz no funciona en el nivel de preprocesador. Lo siento. –

+0

@R Creo que sí. Probé su código y AÑO obtiene el valor correcto de 2011, pero no está claro cómo usarlo (para mí). –

5

lugar de tratar con el formato de la incómoda __DATE__ macro, por qué no rodar su propia?

gcc -DTHIS_YEAR=`/bin/date +%Y` yourprogram.c 

A continuación, el código puede utilizar expresiones como #if THIS_YEAR >= 2020.

+0

oh, yo como este ... más o menos. Un poco demasiado frágil. Es probable que el sistema de construcción cambie en los próximos 10 años y se romperá. –

+1

@MK: también puede tener un '# si' que genera un' # error' si 'THIS_YEAR' no está definido, lo que asegurará que los cambios en el sistema de construcción mantengan esta funcionalidad. –

+0

Si encuentro eso en un sistema de compilación, simplemente agregaría '-DTHIS_YEAR = 2011' a' CFLAGS' ... :-) –

5

Aquí es una solución terrible:

  1. En directorio de cabecera de propósito general de su proyecto, ejecute el (Python) siguiente secuencia de comandos:

    #!/usr/bin/python 
    
    months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 
          'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 
    
    cutoff = 2020 
    #safety = 2025 
    
    for year in range(2011, cutoff): 
        for month in months: 
         for day in range(1, 32): 
          t = open("%s %2d %d" % (month, day, year), "w") 
          t.write("\n"); 
          t.close() 
    
    #for year in range(2011, cutoff): 
    # for month in months: 
    #  for day in range(1, 32): 
    #   t = open("%s %2d %d" % (month, day, year), "w") 
    #   t.write("#error \"Too old\"\n"); 
    #   t.close() 
    

    Descomentar las líneas de salida comentado para producir un mejor diagnóstico mensajes.

  2. En los archivos que necesitan de error después de la fecha de corte, utilice esto:

    #include __DATE__ 
    

que se atreve a usar esto en el código de producción.

+0

esto se está yendo de las manos, pero supongo que eso es lo que solicité :) –

+0

Awesome ! :-) LOL –

+0

+1 para: (1) hacerme reír, y (2) ser lo suficientemente cuerdo como para incluir la primera oración. –

1

__DATE__ no es lo más apropiado para este objetivo:

If the date of translation is not available, an implementation-defined valid date shall be supplied.

Cualquier futuro rota compilador de C que todavía sólo se implementa C99 :) y no cualquiera de sus seguidores pueda fijar la fecha para "Jan  1 1970" o tienen que envolver una vez más allá de la fecha fatal en 2038.

+0

En teoría, sí, esto es cierto (y me río de la frase "_still only_ implementa C99" - ese será el día), pero en la práctica no hay fecha interna del compilador moderno va a fallar antes de 2038, y dado que el OP quiere una advertencia mucho antes de esa fecha, esto debería funcionar. Pero +1 para la corrección técnica. –

+0

No, eso no es solo teórico.Alguien que aún intente compilar una versión del código donde esto no se soluciona en ese momento es muy probable que también use un compilador que no funciona. En particular, si el implementador del compilador usa la misma estrategia y las compilaciones '__DATE__' del compilador (que es legal). Entonces, en esencia, '__DATE__' es la respuesta incorrecta a una pregunta incorrecta. –

Cuestiones relacionadas