Recherche d'erreurs de mémoire dynamique avec les outils de détection d'erreurs de mémoire
Par Parasoft
12 juillet 2012
3 min lire
En utilisant mémoire allouée dynamiquement correctement est une question délicate. Dans de nombreux cas, les programmes continuent à bien fonctionner après une erreur de programmation corruption de mémoire; parfois ils ne plantent pas du tout. Dans cet article, nous examinons comment l'analyse dynamique peut détecter les problèmes de corruption de mémoire courants dans le code C.
Une erreur courante consiste à essayer de réutiliser un pointeur après qu'il a déjà été libéré. Considérez les lignes 22-26 dans le programme suivant qui désalloue les blocs de mémoire avant d'allouer les plus grands:
Pointeurs pendantes
Si vous exécutez ce code via détection d'erreur de mémoire outil tel que Parasoft Insure ++, vous obtiendrez un message d'erreur concernant un «pointeur suspendu» à la ligne 24. Dans ce cas, le bloc pointé par string_so_far est libéré à la ligne 23 puis utilisé dans la ligne suivante.
Wikipédia définit un pointeur suspendu en tant que «pointeurs qui ne pointent pas vers un objet valide du type approprié. Ce sont des cas particuliers de violations de la sécurité de la mémoire. Plus généralement, les références pendantes et les références sauvages sont des références qui ne se résolvent pas vers une destination valide. » Il s'agit d'une classe d'erreurs liées au fait que «la suppression explicite d'un objet de la mémoire ou la destruction de la trame de la pile au retour n'altère pas les pointeurs associés. Le pointeur pointe toujours vers le même emplacement dans la mémoire, même s'il peut désormais être utilisé à d'autres fins. » C'est un problème courant qui passe souvent inaperçu car les programmes avec ces erreurs se compilent souvent sans avertissement et peuvent parfois s'exécuter correctement.
Dans l'exemple ci-dessus, la référence de la mémoire tampon par le pointeur string_so_far est explicitement libérée puis déréférencée. L'analyse dynamique détecte ces erreurs qui peuvent passer inaperçues pendant les tests et même pendant le fonctionnement normal de l'application jusqu'à ce que le mauvais morceau de mémoire soit mal accédé.
Quels autres problèmes de mémoire dynamique les outils de détection des erreurs de mémoire peuvent-ils trouver?
En plus de ce type de problème de mémoire dynamique du pointeur suspendu, détection d'erreur de mémoire outil tel que Parasoft Insure ++ détecte également les erreurs suivantes:
- Lire ou écrire sur des «pointeurs suspendus».
- Passer des «pointeurs pendants» comme arguments à des fonctions ou les renvoyer à partir de fonctions.
- Libérer le même bloc de mémoire plusieurs fois.
- Tentative de libération de la mémoire allouée statiquement.
- Libération de la mémoire de la pile (variables locales).
- Passer un pointeur à free qui ne pointe pas vers le début d'un bloc mémoire.
- Appels à free avec des pointeurs NULL ou non initialisés.
- Passer des arguments absurdes ou des arguments du mauvais type de données à malloc, calloc, realloc ou free.
Analyse au moment de la compilation
Insure ++ détecte les erreurs au moment de la compilation ainsi qu'au moment de l'exécution. Les erreurs de compilation détectées incluent:
- La fonte du pointeur perd de la précision
- Non-concordance dans la spécification de format
- Non-concordance dans le type d'argument
- Le code n'est pas évalué, n'a aucun effet ou est inaccessible
- Identifiant indéfini
- Variable déclarée, mais jamais utilisée
- Retour du pointeur vers la variable locale
- La fonction renvoie une valeur incohérente
- Variables inutilisées
Rapports d'exécution
L'utilisateur exécute ensuite ce programme dans le cadre des tests de cas d'utilisation, tout comme vous utiliseriez le programme d'origine, et Insure ++ signale tous les problèmes détectés. Les rapports Insure ++ incluent des informations détaillées, notamment: sur le type de bogue, le fichier source et le numéro de ligne, le contenu réel de la ligne de code source, l'expression à l'origine du problème, avec des rapports comprenant:
- Le type de bogue, (par exemple EXPR_UNRELATED_PTRCMP)
- Le fichier source et le numéro de ligne, (par exemple foo.cc:42)
- Le contenu réel de la ligne de code source, (par exemple "while (p <g) {")
- L'expression qui a causé le problème, (par exemple «p <g»)
- Informations sur tous les pointeurs et blocs de mémoire impliqués dans le bogue:
- Les valeurs du pointeur
- Les blocs de mémoire pointés (le cas échéant) et tout décalage
- Les informations d'allocation de bloc:
- Trace de pile si allouée dynamiquement.
- Emplacement de la déclaration de bloc, (fichier source et numéro de ligne), s'il est alloué sur la pile ou globalement.
- Trace de pile de la désallocation du bloc, le cas échéant.
- La trace de pile montrant comment le programme est arrivé à l'emplacement du bogue.
Crédit image: xithorien