Habituellement, nous n'écrivons pas de notes sur la sortie de la nouvelle version de l'analyseur PVS-Studio. Cependant, la nouvelle version inclut de nombreux changements intéressants concernant l'analyse du code C et C ++, dont nous aimerions parler à nos utilisateurs.
Java arrive bientôt
Pour être honnête, les dernières innovations les plus intéressantes de PVS-Studio sont toujours cachées. Je veux dire le support dans l'analyseur de langage Java. Il n'y a pas encore de version bêta publique de PVS-Studio pour Java, mais elle sera disponible très bientôt. Si vous souhaitez participer à ses tests, vous pouvez nous écrire en
support (choisissez: Je veux un analyseur pour Java).
Nouveaux diagnostics pour C et C ++
Dans la nouvelle version, nous nous sommes un peu emportés et avons immédiatement ajouté 15 diagnostics à usage général pour C et C ++ (V1021-V1035). Dans une version mineure, de nombreux diagnostics n'ont jamais été ajoutés à la fois. Vous trouverez plus de détails sur chacun des diagnostics dans la
documentation . À mon avis, les plus intéressants parmi les nouveaux diagnostics sont:
- V1026. La variable est incrémentée dans la boucle. Un comportement non défini se produira en cas de dépassement d'entier signé.
- V1033. La variable est déclarée auto en C. Son type par défaut est int.
Diagnostics
V1026 créé sur la base de la
discussion sur le forum linux.org.ru. Le programmeur s'est plaint d'un problème dans le compilateur GCC 8, mais, comme il s'est avéré plus tard, la faute était le code incorrect, conduisant à un comportement indéfini. Regardons ce cas.
Remarque Dans la discussion d'origine, la variable
s est de type
const char * s . De plus, sur la plateforme cible, le type
char n'est pas signé. Par conséquent, pour plus de clarté, j'ai immédiatement écrit dans l'exemple que le type du pointeur est
const 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; }
Le compilateur ne génère pas de code pour l'opérateur AND au niveau du bit (&). Pour cette raison, la fonction renvoie des valeurs négatives, bien que cela ne devrait pas arriver à l'intention du programmeur.
Le développeur estime que c'est un problème dans le compilateur. Mais le programmeur qui a écrit un tel code a en fait tort. La fonction ne fonctionne pas correctement en raison du fait qu'un comportement indéfini s'y produit.
Le compilateur voit qu'une certaine quantité est considérée dans la variable
r . Un débordement de la variable
r ne doit pas se produire. Sinon, il s'agit d'un comportement indéfini que le compilateur ne doit pas prendre en compte et prendre en compte. Ainsi, le compilateur estime que puisque la valeur de la variable
r après la fin du cycle ne peut pas être négative, l'opération
r & 0x7fffffff pour réinitialiser le bit de signe est superflue et le compilateur renvoie simplement la valeur de la variable
r à partir de la fonction.
Diagnostics V1026 est juste conçu pour détecter de telles erreurs. Pour corriger le code, il suffit de lire le hachage à l'aide d'une variable non signée. Version corrigée du code:
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); }
Voyons maintenant un autre diagnostic
V1033 . Il est intéressant de noter que la cause d'erreurs possibles était le nouveau mot clé
auto , qui est apparu en C ++ 11. Et ce n'est pas l'innovation du langage C ++ 11 lui-même qui est coupable, mais les nuances du plan psychologique :). Je vais vous expliquer maintenant. Jetez un oeil à ce code:
float d = 3.14f; int i = 1; auto sum = d + i;
Le voyez-vous comme une erreur? Pensez-y. Voici une image pour que vous ne lisiez pas immédiatement le texte.
Devinez ce qui pourrait être faux? Sinon, voici quelques informations plus intéressantes. La variable
somme sera 4, pas 4,14. Pourquoi?
Maintenant, le lecteur dira que c'était une énigme malhonnête! Le truc, c'est que ce n'est pas du C ++, mais du C.
Il arrive qu'un projet utilise à la fois C ++ et le bon vieux C. Le programmeur s'habitue à utiliser
auto en C ++ et peut accidentellement utiliser ce mot en C. Mais cela signifie autre chose:
autoDéfinit une variable locale comme ayant une durée de vie locale. Le mot clé auto utilise la syntaxe suivante: [auto] data-definition;
Comme la durée de vie locale est la valeur par défaut pour les variables locales, le mot clé auto est extrêmement rarement utilisé.Il s'avère que la
somme variable est de type
int , et c'est pourquoi sa valeur sera 4.
Bien que l'erreur puisse sembler exotique, en fait, dans un projet qui utilise un mélange de fichiers C et C ++, elle est très facile à faire. En conséquence, lors de l'analyse des fichiers C, PVS-Studio met en garde contre de telles constructions suspectes.
Autres innovations
Ajout de la possibilité
de vérifier les projets pour le système de
construction Waf .
Nous continuons
à développer l' analyseur vers des systèmes embarqués. Cette version ajoute le support de vérification de projet pour le GNU Arm Embedded Toolchain, le compilateur Arm Embedded GCC.
Lors de l'analyse de projets pour le compilateur Visual C ++ (cl.exe, projets vcxproj pour Visual Studio / Standalone), le rapport de l'analyseur stocke désormais le registre dans les chemins d'accès aux fichiers vérifiés. Le raffinement latéral semble plus facile qu'il ne l'est vraiment. Lors du prétraitement des fichiers, le compilateur cl.exe gâche le cas dans les noms de fichiers. Et vous devez les restaurer dans l'analyseur.
Ajout de la possibilité d'utiliser les fichiers pvsconfig de CLMonitor / Standalone sur Windows.
Un mode d'analyse incrémentielle a été ajouté pour le module pvs-studio-analzyer / CMake. Le module PVS-Studio CMake peut désormais être utilisé sous Windows pour les projets utilisant le compilateur Visual C ++ (cl.exe).
Ajout de la prise en charge de l'analyse incrémentielle pour les projets Visual Studio .NET Core / .NET Standard.
Liens annexes
- PVS-Studio. Historique des versions .
- Andrey Karpov. Un comportement indéfini est plus proche que vous ne le pensez .
- Will Dietz, Peng Li, John Regehr et Vikram Adve. Comprendre le dépassement d'entier en C / C ++ .
- Egor Bredikhin. Développement d'un nouvel analyseur statique: PVS-Studio Java .