Découvrez comment intégrer facilement l'analyse statique, les tests unitaires et d'autres méthodes de test de logiciels C et C++ dans votre pipeline CI/CD. Inscrivez-vous pour la démo >>

Analyse statique et détection des erreurs d'exécution sur les plates-formes 64 bits

Par Parasoft

14 octobre 2010

3  min lire

Dans mon postes précédents, J'ai couvert une stratégie en quatre étapes pour préparer l'application pour le processus de portage 64 bits:

  1. Appliquer le test de mutation pour effectuer la détection des erreurs d'exécution
  2. Utiliser l'analyse de code statique pour identifier le code sujet aux erreurs et non portable
  3. Répéter la détection des erreurs d'exécution
  4. Effectuer des tests unitaires (facultatif)

Pour conclure ce sujet, j'aimerais présenter une stratégie pour identifier les défauts sur le processeur 64 bits:

  1. Recompilez le code sur le processeur 64 bits
  2. Répéter code d'analyse statique inspection
  3. Lier et construire
  4. Lancez l'application
  5. Répéter la détection des erreurs d'exécution

Étape 1: Recompilez le code sur le processeur 64 bits

Recompilez votre application sur le processeur 64 bits. Si vous avez du mal à le compiler, résolvez toutes les bizarreries liées aux variations du compilateur. Vous pouvez également créer des règles d'analyse de code statiques qui identifieront automatiquement le code associé à ces bizarreries afin d'éviter que ces problèmes de compilation ne se reproduisent à l'avenir.

Certaines règles à prendre en compte sont celles qui indiquent un code difficile à porter (en 64 bits) et sujet aux erreurs. Par exemple, considérez les exemples suivants (plus de détails sont fournis dans ce poster):

Règles qui exposent un code sujet aux erreurs

  • Ne renvoyez jamais une référence à un objet local ou à un pointeur déréférencé initialisé par «nouveau» dans la fonction.
  • Ne convertissez jamais un const en non-const. Cela peut nuire à l'intégrité des données en autorisant le changement de valeurs supposées constantes.
  • Si une classe a des fonctions virtuelles, elle doit avoir un destructeur virtuel. Cette norme empêche les fuites de mémoire dans les classes dérivées.
  • Les fonctions membres publiques doivent renvoyer des descripteurs const aux données membres.
  • Lorsque vous fournissez des descripteurs non const aux données des membres, vous compromettez l'encapsulation en permettant aux appelants de modifier les données des membres en dehors des fonctions membres.
  • Un pointeur vers une classe ne doit pas être converti en un pointeur d'une seconde classe à moins qu'il n'hérite de la seconde. Cette conversion descendante «invalide» peut entraîner des pointeurs sauvages, des problèmes de corruption des données et d'autres erreurs.
  • N'accédez pas directement aux données globales à partir d'un constructeur.

Un ensemble de règles personnalisé peut être créé à partir de la sélection des règles critiques nécessaires uniquement pour cette tâche particulière. D'autres règles peuvent être ajoutées ultérieurement, si nécessaire.

Règles qui exposent un code de port difficile

Après avoir localisé et réparé ce code sujet aux erreurs, commencez à rechercher du code qui fonctionne correctement sur votre plate-forme / architecture actuelle, mais qui pourrait ne pas être correctement porté. Certaines règles applicables à la plupart des projets de portage 64 bits incluent:

  • Utilisez les types standard le cas échéant.
  • Passez en revue toutes les utilisations existantes des types de données longs dans le code source.
  • Examinez toutes les instances d'affectation restreinte. Évitez de telles affectations car l'attribution d'une valeur longue à un int entraînera une troncature de la valeur 64 bits.
  • Trouvez des moulages rétrécis. Utilisez des castes restrictives sur les expressions, pas des opérandes.
  • Trouvez des casts de long * à int *. Dans un environnement 32 bits, ceux-ci peuvent avoir été utilisés de manière interchangeable. Examinez toutes les instances d'affectations de pointeurs incompatibles.
  • Trouvez des casts de int * à long *. Dans un environnement 32 bits, ceux-ci peuvent avoir été utilisés de manière interchangeable. Examinez toutes les instances d'affectations de pointeurs incompatibles.
  • Trouvez des valeurs longues initialisées avec des littéraux int. Évitez de telles initialisations car les constantes intégrales peuvent être représentées sous forme de types 32 bits même lorsqu'elles sont utilisées dans des expressions avec des types 64 bits.
  • Localisez les littéraux int dans les opérations binaires pour lesquelles le résultat est affecté à une valeur longue. Une multiplication de 64 bits est souhaitée si le résultat est une valeur de 64 bits.
  • Trouvez les constantes int utilisées dans les expressions 64 bits. Utilisez des valeurs 64 bits dans des expressions 64 bits.
  • Recherchez les utilisations d'expressions multiplicatives ne contenant pas de type 64 bits dans l'un ou l'autre des opérandes. Pour que les expressions intégrales produisent des résultats 64 bits, au moins l'un des opérandes doit avoir un type de données 64 bits signé ou non signé.
  • Utilisez les suffixes appropriés sur les constantes littérales entières et flottantes si votre compilateur les autorise.

Étape 2: Répétez l'inspection du code d'analyse statique

Une fois que vous avez recompilé le code, effectuez à nouveau une analyse de code statique pour vérifier si le nouveau code est conforme à toutes les normes de codage appropriées. À ce stade, chaque modification qui aurait dû être effectuée mais qui n'a pas été effectuée est une erreur. Corrigez ces erreurs immédiatement ! Vous ne voulez pas rechercher ces erreurs lorsque l'application est en cours d'exécution.

Étape 3: liez et construisez

Liez votre application et essayez de la créer.

Étape 4: Lancez l'application

À ce stade, vous devez essayer d'exécuter votre code. Si vous rencontrez un problème lors de l'exécution du code sur le processeur 64 bits, utilisez un cadre de test unitaire pour exécuter le code fonction par fonction; de cette façon, vous pouvez vider exactement ce qui dans le code n'est pas portable. Testez la fonction, puis résolvez le problème. Continuez ce processus jusqu'à ce que toute l'application soit en cours d'exécution.

Étape 5: Répétez la détection des erreurs d'exécution

Une fois l'application en cours d'exécution, vous voudrez répéter la détection des erreurs d'exécution, car le processus de portage est susceptible de provoquer de nouveaux problèmes qui n'ont pas pu être détectés avant le port (par exemple, de nouveaux problèmes de corruption de la mémoire ou des comportements différents). Si la détection d'erreurs d'exécution pose des problèmes, corrigez tous les bogues liés au portage.

***
Crédit photo: Jurvetson

Envie d'en savoir plus? Jetez un œil à notre Parasoft Insure ++La page produit de pour voir comment la détection des erreurs d'exécution peut exposer la corruption de la mémoire, les fuites de mémoire, l'accès en dehors des limites du tableau, les pointeurs non valides et d'autres défauts.

Par Parasoft

Les outils de test de logiciels automatisés de pointe de Parasoft prennent en charge l'ensemble du processus de développement logiciel, depuis le moment où le développeur écrit la première ligne de code jusqu'aux tests unitaires et fonctionnels, jusqu'aux tests de performance et de sécurité, en exploitant des environnements de test simulés en cours de route.

Recevez les dernières nouvelles et ressources sur les tests de logiciels dans votre boîte de réception.