projprog/MEMCHECK.md
2021-11-19 19:11:50 +01:00

4.8 KiB

MEMCHECK

Exercice 1

Valgrind est disponible sur les plateformes suivantes :

  • x86/Linux: up to and including SSSE3, but not higher -- no SSE4, AVX, AVX2. This target is in maintenance mode now..

  • AMD64/Linux: up to and including AVX2. This is the primary development target and tends to be well supported.

  • PPC32/Linux, PPC64/Linux, PPC64LE/Linux: up to and including Power8.

  • S390X/Linux: supported.

  • ARM/Linux: supported since ARMv7.

  • ARM64/Linux: supported for ARMv8.

  • MIPS32/Linux, MIPS64/Linux: supported.

  • X86/Solaris, AMD64/Solaris, X86/illumos, AMD64/illumos: supported since Solaris 11.

  • X86/Darwin (10.10, 10.11), AMD64/Darwin (10.10, 10.11): supported.

  • ARM/Android, ARM64/Android, MIPS32/Android, X86/Android: supported.

    (ce n'est pas du tout un copier-coller ...)

Voici les erreurs que memcheck peut détecter :

  • Les accès mémoire interdits (dépassement, accès après libération, dépassement de la pile)
  • Quelles variables ont des valeurs indéfinies (car pas initialisées ou déduites de variables non initialisées).
  • Libération incorrecte du tas (par exemple double-libération ou malloc ne correspondant pas aux free
  • Quand la source et le but interferent en utilisant memcopy
  • Allocation d'une quantité de mémoire potentiellement incorrecte (négative par exemple)
  • Fuites de mémoire

Valgrind ralentit l'execution et augmente l'utilisation mémoire de manière drastique.

Aussi, ce n'est pas un outil magique et passe derrière certaines erreurs.

Exercice 2

Liste des erreurs:

Invalid write of size 1
   at 0x1091C2: main (MEMCHECK.2.c:12)
 Address 0x4a30428 is 0 bytes after a block of size 1,000 alloc'd
   at 0x483877F: malloc (vg_replace_malloc.c:307)
   by 0x10919D: main (MEMCHECK.2.c:10)

Cette erreur trahit une tentative de modifier une case mémoire hors du bloc qui a été alloué à la variable.


Invalid read of size 1
   at 0x4838CD4: __strlen_sse2 (vg_replace_strmem.c:462)
   by 0x48D79EE: vfprintf (vfprintf.c:1638)
   by 0x48DE605: printf (printf.c:33)
   by 0x1091F8: main (MEMCHECK.2.c:17)
 Address 0x4a4a428 is 0 bytes after a block of size 1,000 alloc'd
   at 0x483577F: malloc (vg_replace_malloc.c:299)
   by 0x10919D: main (MEMCHECK.2.c:10)

Cette erreur se déclenche car le programme essaie de lire une valeur hors du bloc alloué à la variable. Ici, ça vient du problème de la variable texte qui n'a pas de caractère de fin '\0'et printf ne sait donc pas quand s'arrêter.


Conditional jump or move depends on uninitialised value(s)
at 0x483CB98: strcmp (vg_replace_strmem.c:847)
by 0x1091DC: main (MEMCHECK.2.c:16)

Le strcmp s'applique une première fois à la variable mdp qui n'est au départ pas initialisée.


Invalid free() / delete / delete[] / realloc()
  at 0x48369AB: free (vg_replace_malloc.c:530)
  by 0x1092C7: main (MEMCHECK.2.c:36)
Address 0x4a4a040 is 0 bytes inside a block of size 1,000 free'd
  at 0x48369AB: free (vg_replace_malloc.c:530)
  by 0x109234: main (MEMCHECK.2.c:21)
Block was alloc'd at
  at 0x483577F: malloc (vg_replace_malloc.c:299)
  by 0x10919D: main (MEMCHECK.2.c:10)

La variable texte est libérée deux fois, d'où cette erreur.


1,000 bytes in 1 blocks are definitely lost in loss record 1 of 1
   at 0x483577F: malloc (vg_replace_malloc.c:299)
   by 0x10919D: main (MEMCHECK.2.c:10)

Si on ne réessaie pas avec un mot de passe directement invalide, la mémoire allouée à texte par malloc n'est jamais libérée.

Exercice 4

Ce programme affiche foo bar\n. Simplement.

La troisième ligne du main est intriguante. Elle essaie de modifier le 7e caractère de la chaine foo. On peut imaginer que les chaines de caractère "foo" et "bar" sont stoquées côte à côte dans la mémoire de cette manière: foo\0bar\0. La modification modifierai donc la mémoire en foo\0barz plus le reste de la mémoire (comme le caractère z par exemple). Le problème est que cette mémoire est allouée en statique au démarage du programme. Donc elle ne peut pas être modifiée. Et pourtant, Valgrind ne détecte aucune erreur. Je pense que c'est dû au fait que le noyau C ne renvoie pas d'erreur lorsque cette mémoire en lecture seule demande à être modifiée. Cela n'a aucun effet, mais pas non plus d'erreur.

Exercice 5

J'ai corrigé le premier exo. J'avais seulement deux erreurs: Une due à une mauvaise gestion du scanf et l'autre due à un simple oubli de libérer les variables.

Pour le second exercice, une petite erreur sur le scanf, mais je pense que l'erreur n'est pas importante. En effet, Valgrind râle parce que scanf utilise une variable non initialisée (ce qui est normal, puisque c'est cette fonction qui lui donne ça premiere valeur). Remplacer malloc par calloc corrige ce problème, mais est un peu inutile.