2010-08-09 12 views
10

Actualmente estoy trabajando en un proyecto C que debe ser bastante portátil entre diferentes entornos de construcción. El proyecto se dirige a sistemas que cumplen con POSIX en un entorno C alojado.Prueba de conformidad ISO C estricta

Una forma de lograr un buen grado de portabilidad es codificar conforme a un estándar elegido, pero es difícil determinar si una unidad de traducción determinada cumple estrictamente con ISO C. Por ejemplo, podría violar alguna traducción límites, o puede estar confiando en un comportamiento indefinido, sin ningún mensaje de diagnóstico del entorno de compilación. Ni siquiera estoy seguro de si es posible verificar la conformidad estricta de proyectos grandes.

Con esto en mente, es allí cualquier compilador, herramienta o método para la prueba de estricta ISO C conformidad bajo un estándar dado (por ejemplo, C89 o C99) de una unidad de traducción?

Cualquier ayuda es apreciada.

Respuesta

4

En general, no es posible encontrar un comportamiento indefinido en tiempo de ejecución. Por ejemplo, considere

void foo(int *p, int *q) 
{ 
    *p = (*q)++; 
    ... 

que está definido si p == q. Si eso puede ocurrir no puede determinarse de antemano sin resolver el problema de detención.

(Editado para corregir error CAF señaló. Gracias, CAF.)

+0

Tu ejemplo es fantástico. Nunca he pensado en expresiones de puntero tan simples. Creí que cada condición indefinida podría ser detectada en tiempo de análisis. – alecov

+3

Su ejemplo está realmente bien, incluso si 'p == q' - quizás usted quiso decir' * p = (* q) ++ ', que no está definido si' p == q'? – caf

3

No realmente. El estándar C no establece ningún límite mínimo absoluto en las unidades de traducción que deben aceptarse. Como tal, un corrector perfectamente preciso sería trivial para escribir, pero completamente inútil en la práctica:

#include <stdio.h> 

int main(int argc, char **argv) { 
    int i; 
    for (i=1; i<argc; i++) 
     fprintf(stderr, "`%s`: Translation limit (potentially) exceeded.\n", argv[i]); 
    return 0; 
} 

Sí, esto rechaza todo, no importa lo trivial. Eso está de acuerdo con el estándar. Como dije, es completamente inútil en la práctica. Desafortunadamente, no se puede hacer mucho mejor: cuando decides realizar un cambio a una implementación diferente, puedes encontrar un límite de recursos extraños que nunca antes has visto, así que cualquier código que escribas (hasta un " hola mundo ") podría potencialmente exceder un límite de recursos a pesar de ser permitido por docenas o incluso cientos de compiladores en/para sistemas mucho más pequeños.

Editar:

Por qué un programa "hola mundo" no es estrictamente conformando

En primer lugar, vale la pena volver a expresar la definición de "estrictamente conforme": "Un programa estrictamente conformación sólo los utilizará características del lenguaje y la biblioteca especificadas en esta Norma Internacional.2) No producirá resultados dependientes de ningún comportamiento no especificado, indefinido o definido por la implementación, y no deberá exceder ningún límite mínimo de implementación. "

En realidad hay un número de razones "Hola, Mundo" no se ajusta estrictamente. En primer lugar, como se indicó anteriormente, los requisitos mínimos para los límites de implementación son completamente insignificantes, aunque debe haber algún programa que cumpla con ciertos límites que se aceptarán, no se debe aceptar otro programa, incluso si no lo hace t incluso se acercan a ninguno de esos límites. Dada la forma en que se establece el requisito, está abierto a la pregunta (en el mejor de los casos) si existe algo así como un programa que no exceda ningún límite de implementación mínimo, porque el estándar realmente no define ningún límite mínimo de implementación.

Segundo, durante la fase 1 de la traducción: "Los caracteres multibyte del archivo de origen físico se asignan, de una manera definida de implementación, al conjunto de caracteres de origen ..." (§5.1.1.2/1). Desde "Hello, World!" (o la variante que prefiera) se suministra como un literal de cadena en el archivo de origen, se puede (se) correlacionar de una manera definida por la implementación con el conjunto de caracteres de origen. Una implementación es libre de decidir que (para un ejemplo idiota) los literales de cadena estarán codificados en ROT13, y siempre que ese hecho esté documentado adecuadamente, es perfectamente legítimo.

En tercer lugar, la salida normalmente se escribe a través de stdout. stdout es una secuencia de texto. De acuerdo con el estándar: "Los caracteres pueden tener que ser agregados, alterados o eliminados en la entrada y salida para cumplir con las diferentes convenciones para representar el texto en el entorno de host. Por lo tanto, no es necesario que haya una correspondencia uno a uno entre los caracteres. en una corriente y aquellos en la representación externa ". (§7.19.2/2) Como tal, una implementación podría (por ejemplo) hacer la compresión de Huffman en la salida (el lunes, el miércoles o el viernes).

Por lo tanto, tenemos (al menos) tres puntos distintos en los que la salida de un "¡Hola mundo!" depende de las características definidas por la implementación, cualquiera de las cuales evitaría que se ajuste a la definición de un programa estrictamente conforme.

+0

Esto no está de acuerdo con la norma. Ver §5.2.4.1 Límites de traducción. –

+0

@Stephen: sí, lo es. El requisito es: "La implementación debe poder traducir y ejecutar al menos un programa que contenga al menos una instancia de cada uno de los siguientes límites:". Solo * un * programa específico, y ni siquiera parece ser un requisito para documentar qué es ese programa. Todas las entradas posibles pueden fallar, excepto una específica que no necesita ser identificada ... –

+1

del Estándar ISO C99, §4 Conformidad: "Un programa estrictamente conforme debe usar solo aquellas características del idioma y la biblioteca especificadas en este Norma Internacional. No producirá resultados dependientes de ningún comportamiento indeterminado, indefinido o definido por la implementación, y no deberá exceder ningún límite mínimo de implementación ". ¿Por qué, por lo tanto, una implementación obviamente simple del programa Hello World no sería estrictamente conforme en este caso? – alecov

0

gcc tiene niveles de advertencia que intentarán precisar varios aspectos de la conformidad ANSI. Pero el sombrero es solo un punto de partida.

0

Es posible comenzar con gcc -std=c99 o gcc -ansi -pedantic.

0

Buena suerte con eso. Trate de evitar enteros con signo, porque:

int f(int x) 
{ 
return -x; 
} 

puede invocar UB.