Por lo general, no escribimos notas sobre el lanzamiento de la nueva versi贸n del analizador PVS-Studio. Sin embargo, la nueva versi贸n incluye muchos cambios interesantes con respecto al an谩lisis del c贸digo C y C ++, que nos gustar铆a contarles a nuestros usuarios.
Java pr贸ximamente
Para ser sincero, las 煤ltimas y m谩s interesantes innovaciones en PVS-Studio todav铆a est谩n ocultas. Me refiero a soporte en el analizador de lenguaje Java. Todav铆a no existe una versi贸n beta p煤blica de PVS-Studio para Java, pero estar谩 disponible muy pronto. Si desea participar en sus pruebas, puede escribirnos en
soporte (elija: Quiero un analizador para Java).
Nuevos diagn贸sticos para C y C ++
En la nueva versi贸n, nos dejamos llevar un poco e inmediatamente agregamos 15 diagn贸sticos de uso general para C y C ++ (V1021-V1035). En una versi贸n menor, tantos diagn贸sticos nunca se han agregado a la vez. Se pueden encontrar m谩s detalles sobre cada uno de los diagn贸sticos en la
documentaci贸n . En mi opini贸n, los m谩s interesantes entre los nuevos diagn贸sticos son:
- V1026. La variable se incrementa en el bucle. Se producir谩 un comportamiento indefinido en caso de desbordamiento de entero con signo.
- V1033. La variable se declara como autom谩tica en C. Su tipo predeterminado es int.
Diagn贸stico
V1026 creado en base a la
discusi贸n en el foro linux.org.ru. El programador se quej贸 de una falla en el compilador GCC 8, pero, como result贸 m谩s tarde, la falla fue el c贸digo incorrecto, lo que condujo a un comportamiento indefinido. Miremos este caso.
Nota En la discusi贸n original, la variable
s es de tipo
const char * s . Adem谩s, en la plataforma de destino, el tipo
char no est谩 firmado. Por lo tanto, para mayor claridad, escrib铆 inmediatamente en el ejemplo que el tipo del puntero es
constante unsigned char * .
int foo(const unsigned char *s) { int r = 0; while(*s) { r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3) ^ (r >> 1); s++; } return r & 0x7fffffff; }
El compilador no genera c贸digo para el operador AND a nivel de bit (&). Debido a esto, la funci贸n devuelve valores negativos, aunque esto no deber铆a suceder con la intenci贸n del programador.
El desarrollador cree que esto es una falla en el compilador. Pero el programador que escribi贸 dicho c贸digo est谩 realmente equivocado. La funci贸n no funciona correctamente debido al hecho de que se produce un comportamiento indefinido en ella.
El compilador ve que se considera una cierta cantidad en la variable
r . El desbordamiento de la variable
r no deber铆a ocurrir. De lo contrario, este es un comportamiento indefinido que el compilador no debe considerar y tener en cuenta. Entonces, el compilador cree que dado que el valor en la variable
r despu茅s del final del ciclo no puede ser negativo, la operaci贸n
r & 0x7fffffff para restablecer el bit de signo es superflua y el compilador simplemente devuelve el valor de la variable
r de la funci贸n.
Diagnostics V1026 est谩 dise帽ado para detectar tales errores. Para arreglar el c贸digo, es suficiente leer el hash usando una variable sin signo. Versi贸n corregida del c贸digo:
int foo(const unsigned char *s) { unsigned r = 0; while(*s) { r += ((r * 20891 + *s *200) | *s ^ 4 | *s ^ 3) ^ (r >> 1); s++; } return (int)(r & 0x7fffffff); }
Ahora veamos otro diagn贸stico
V1033 . Es interesante porque la causa de posibles errores fue la nueva palabra clave
autom谩tica , que apareci贸 en C ++ 11. Y no es la innovaci贸n del lenguaje C ++ 11 en s铆 mismo lo que es culpable, sino los matices del plan psicol贸gico :). Te lo explicar茅 ahora. Echa un vistazo a este c贸digo:
float d = 3.14f; int i = 1; auto sum = d + i;
驴Lo ves como un error? Piensa en eso. Aqu铆 hay una imagen para que no lea m谩s el texto de inmediato.
驴Adivina qu茅 podr铆a estar mal? Si no, aqu铆 hay informaci贸n m谩s interesante. La variable
suma ser谩 4, no 4.14. Por qu茅
隆Ahora el lector dir谩 que fue un enigma deshonesto! Lo que pasa es que esto no es C ++, sino C.
Sucede que un proyecto usa C ++ y el viejo C. El programador se acostumbra a usar
auto en C ++ y accidentalmente puede usar esta palabra en C. Pero significa algo m谩s all铆:
autoDefine una variable local como teniendo una vida local. La palabra clave auto utiliza la siguiente sintaxis: [auto] data-definition;
Como el tiempo de vida local es el predeterminado para las variables locales, la palabra clave auto se usa extremadamente raramente.Resulta que la
suma variable es de tipo
int , y es por eso que su valor ser谩 4.
Aunque el error puede parecer ex贸tico, de hecho, en un proyecto que usa una mezcla de archivos C y C ++, es muy f谩cil de hacer. En consecuencia, al analizar archivos C, PVS-Studio advierte sobre tales construcciones sospechosas.
Otras innovaciones
Se agreg贸 la capacidad
de verificar proyectos para el sistema de
compilaci贸n Waf .
Continuamos
desarrollando el analizador hacia sistemas embebidos. Esta versi贸n agrega soporte de verificaci贸n de proyectos para GNU Arm Embedded Toolchain, compilador Arm Embedded GCC.
Al analizar proyectos para el compilador de Visual C ++ (cl.exe, proyectos vcxproj para Visual Studio / Standalone), el informe del analizador ahora almacena el registro en las rutas a los archivos verificados. El refinamiento lateral parece m谩s f谩cil de lo que realmente es. Al preprocesar archivos, el compilador cl.exe estropea el caso en los nombres de archivo. Y tiene que restaurarlos nuevamente al analizador.
Se agreg贸 la capacidad de usar archivos pvsconfig de CLMonitor / Standalone en Windows.
Se ha agregado un modo de an谩lisis incremental para el m贸dulo pvs-studio-analzyer / CMake. El m贸dulo PVS-Studio CMake ahora se puede usar en Windows para proyectos que usan el compilador Visual C ++ (cl.exe).
Se agreg贸 soporte para an谩lisis incremental para proyectos de .NET Core / .NET Standard Visual Studio.
Enlaces de sitio
- PVS-Studio. Historial de versiones
- Andrey Karpov. El comportamiento indefinido est谩 m谩s cerca de lo que piensas .
- Will Dietz, Peng Li, John Regehr y Vikram Adve. Comprender el desbordamiento de enteros en C / C ++ .
- Egor Bredikhin. Desarrollo de un nuevo analizador est谩tico: PVS-Studio Java .