Code C++, MISRA et Cpptest
Bonjour,
J'ai pour mission de passer Cpptest (de Parasoft) sur un code (que je n'ai pas écrit) afin de vérifier sa compatibilité avec un certain nombre de règles MISRA.
Alors, soit le module Cpptest n'est pas au moins, soit un truc m'échappe mais j'ai l'impression de tourner en rond.
J'utilise une fonction qsort personnalisée à laquelle je ne peux toucher (et il n'est pas question de ne pas appeler cette fonction). Cette fonction a pour prototype :
Code:
1 2 3 4
| void mon_qsort (void *tableau,
size_t nb_elem,
size_t taille_elem,
mon_int (*compare) (const void *, const void *)); |
Je l'utilise de la manière suivante :
Code:
1 2 3 4
| mon_qsort((void *)mon_tableau,
(size_t) nombre_elements,
(size_t) taille_elem,
(mon_int (*) (const void *, const void *))ma_comparaison); |
Le code de la fonction ma_comparaison est le suivant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| mon_int ma_comparaison(const ma_structure * const i_pa, const ma_structure * const i_pb)
{
mon_int resultat;
if (i_pa->valeur > i_pb->valeur)
{
resultat = -1;
}
else if (i_pa->valeur < i_pb->valeur)
{
resultat = 1;
}
else
{
resultat = 0;
}
return resultat;
} |
Quand je passe Cpptest, j'ai une erreur MISRA sur le qsort, en particulier pour la quatrième entrée :
"MISRA2008-5_2_6 : Do not convert a pointer to function 'ma_comparaison' to any other pointer type".
Qu'à cela ne tienne, je décide de faire quelques petits changement. L'appel à mon_qsort devient :
Code:
1 2 3 4
| mon_qsort (void *)mon_tableau,
(size_t) nombre_elements,
(size_t) taille_elem,
ma_comparaison); |
et ma fonction de comparaison est modifiée de la façon suivante. Si je n'ai plus d'erreur MISRA sur le qsort, j'en ai dans mon code maintenant (que je mets en commentaires) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| mon_int ma_comparaison(const void * const i_pa, const void * const i_pb)
{
mon_int resultat;
const ma_structure * const pa = static_cast<const ma_structure *>(i_pa); //MISRA2008-5_2_8 : do not convert pointer to void type to an object pointer type 'const mon_namespace::ma_structure *'
const ma_structure * const pb = static_cast<const ma_structure *>(i_pb); //MISRA2008-5_2_8 : do not convert pointer to void type to an object pointer type 'const mon_namespace::ma_structure *'
if (pa->valeur > pb->valeur)
{
resultat = -1;
}
else if (pa->valeur < pb->valeur)
{
resultat = 1;
}
else
{
resultat = 0;
}
return resultat;
} |
Pas spécialement convaincu, je change les static_cast en dynamic_cast.
Mes erreurs MISRA disparaissent pour laisser place à d'autres... absolument incompréhensibles à mes yeux :
Code:
1 2 3 4 5 6 7 8 9 10 11
| mon_int ma_comparaison(const void * const i_pa, // MISRA2008-0_1_11 : Parameter 'i_pa' is not used.
const void * const i_pb) // MISRA2008-0_1_11 : Parameter 'i_pb' is not used.
{
mon_int resultat;
const ma_structure * const pa = dynamic_cast<const ma_structure *>(i_pa); //MISRA2008-01_3_a : Local variable 'pa' declared but not used
//MISRA2008-01_3_b : Local variable 'pa' declared but not used
const ma_structure * const pb = dynamic_cast<const ma_structure *>(i_pb); //MISRA2008-01_3_a : Local variable 'pb' declared but not used
//MISRA2008-01_3_b : Local variable 'pb' declared but not used
[...]
} |
Comment peut-il dire que les paramètres et variables ne sont pas utilisés ???
Cpptest est-il fiable, comme outil.
Y a-t-il un moyen de faire autrement en gardant l'esprit du code ?
Merci d'avance pour votre aide.
Code C++, MISRA et Cpptest
Citation:
Envoyé par
Luc Hermitte
Vois avec tes supérieurs et tes clients si le respect de cette règle est plus important que l'utilisation de la fonction.
Dans la mesure où la fonction est une fonction validée déjà prête à utilisation car portée sur cible, on ne va pas en changer (j'aurais peut-être dû préciser que c'était destiné à être porté en temps réel).
Citation:
Envoyé par
Luc Hermitte
PPS: dynamic_cast n'a aucun rapport avec ce que tu cherches à faire. Le seul cast valide ici est un static_cast.
D'accord, mais pourquoi ? J'avoue que j'ai un peu du mal à saisir la nuance. Le static_cast, si j'ai bien compris, vérifie que c'est valable à la compilation alors que le dynamic_cast le fait à l'exécution, mais si tu pouvais m'expliquer pourquoi le static_cast est le SEUL valable, je crois que je me coucherai moins bête ce soir.
Citation:
Envoyé par
Luc Hermitte
Sauf que MISRA t'interdit ces manipulations vu que le C++ offre un typage plus fort que le C grâce aux templates.
C'est un code hérité d'un code C. C'est un peu bâtard, je le conçois.
MISRA n'aurait pas râlé si j'avais fait un cast classique (monpointeur *) si c'était du C pur ?
Merci pour les réponses, en attendant.
Code C++, MISRA et Cpptest
Citation:
Envoyé par
Luc Hermitte
Merci pour le lien.
Citation:
Envoyé par
Luc Hermitte
Les règles qui coincent sont des règles de MISRA-C++ parce que l'on sait peut écrire du code plus robuste en C++ grâce aux templates. Donc effectivement, si tu n'appliques que MISRA-C, parce que le code serait alors uniquement en C, il n'y aura pas de problème.
Encore que...
Citation:
Envoyé par
Luc Hermitte
Mais je le rappelle, la bonne démarche n'est pas de triturer le code pour que ça passe comme par magie sans que l'on ne sache pourquoi (le but des règles MISRA est aussi de combattre la magie des étoiles). C'est de se dire à un moment donné : c'est comme ça que l'on veut procéder et on veut, main dans la main avec le client, qu'il valide notre choix avec une dérogation qu'il nous concèdera officiellement. Un client peut tout à fait comprendre la notion de faux positif. Si vous êtes sur de l'embarqué où le C est une tradition, il acceptera. Et surtout s'il vous a fait signer l'utilisation de MISRA-C++, c'est le seul qui puisse décoincer la situation: soit la conformité à un ensemble de règles, soit l'utilisation d'une fonction estampillée OK par XXX.
C'est un peu plus compliqué que ça : je suis parachuté sur un code que je n'ai pas écrit pour faire passer MISRA dessus et montrer qu'il est grosso modo MISRA-compatible. Par contre, il n'est plus temps de tout réécrire de zéro. Donc on corrige ce qui à l'évidence à été écrit parfois de manière un peu légère pour renforcer les vérifications de sécurité mais on ne repart pas à zéro. Quant au client, je ne suis même pas sûr qu'il comprenne beaucoup dès lors qu'on rentre dans les détails. :mrgreen:
Néanmoins, au-delà de ces problèmes, je souhaitais savoir si certains avaient déjà eu affaire à CppTest. Parce que dans ma boîte, ça semble être une religion... Mais quand je vois CppTest me conseiller de passer une variable affectée à droite et à gauche en const ou qu'il me dit qu'un paramètre n'est pas utilisé contre toute évidence, j'avoue que la confiance que j'ai dans cet outil en prend un sérieux coup.
Merci quand même pour les réponses.
Code C++, MISRA et Cpptest
Citation:
Envoyé par
dragonjoker59
La seule conversion de pointeur autorisée si je ne me trompe est la conversion vers void *
En fait, j'ai fini par comprendre que quand on a un void *, MISRA ne veut pas qu'on le transtype explicitement.
Par exemple, avec calloc ou malloc, il faut faire
Code:
int * p = malloc(n * sizeof(int));
et non pas
Code:
int * p = (int *)malloc(n * sizeof(int));
Là, j'avoue, je tombe un peu des nues, ça va à l'encontre de tout ce qu'on m'a appris ("point de transtypage implicite ne feras").