IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

free() ne fonctionne pas


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Juillet 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Juillet 2015
    Messages : 7
    Par défaut free() ne fonctionne pas
    Bonjour a tous,

    Mon problème est très simple, mes free ne fonctionne pas, je m'en suis aperçu en manipulant des listes chaine, mais le probleme apparait de toute maniere sur des programmes beaucoup plus simple.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int		main(void)
    {
    	char	*str;
     
    	str = malloc(sizeof(char) * 3 + 1);
     
    	str[0] = 'a';
    	str[1] = 'b';
    	str[2] = 'c';
    	str[3] = '\0';
     
    	printf("str -> %s\n", str);
    	free(str);
    	printf("str -> %s\n", str);
    	return (0);
    }
    Me donne en sortie : -> abc
    -> abc
    alors que je viens de desalouer l'adresse.
    J'ai essayer plein de trucs sans succès, Je suis sur mac os et j'utilise iTerm et ohmyzsh. J'ai essayer sur la machine d'un amis sur linux et son programme avec le meme code fonctionne.

    Merci de votre aide !

  2. #2
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Que devrait-il se passer selon toi ? Lis bien la page de manuel.

    Surtout : ton code est invalide. Consulter (ou utiliser d'une quelconque manière) la valeur d'une variable préalablement passée à free entraîne un comportement indéterminé.

    Puisque, de plus, cette fonction ne retourne aucune valeur tu n'as aucun moyen de savoir si l'appel a « fonctionné » . Tu dois faire aveuglément confiance au comportement décris par la norme et à ton système, rassurant non ?


    Dans un contexte de sécurité informatique (stockage d'informations sensibles), il est d'usage de faire un wipe sur le buffer avant de le libérer. Ce n'est pas le comportement par défaut.

  3. #3
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour.

    Désallouer n'implique pas nécessairement de mettre les bits à 0.
    Cela implique juste que la mémoire est libre et que le programme peut en faire ce qu'il veut, par exemple la réserver lors d'un prochain appel à malloc.

    Si ton compilateur n'a pas choisi de mettre les bits à 0 après l'appel à free, c'est pour avoir un très léger gain de performances. En effet, changer une valeur a un petit coût.

  4. #4
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Bonjour,

    je rajouterai que c'est aussi un source d'erreur classique qui fait qu'on retrouve souvent des sujets comme «mon programme ne fonctionne plus à un endroit que je n'ai pas modifié», «ma variable disparaît», ...

    Il est important d'avoir de la rigueur mais aussi un outil permettant de repérer ces erreurs. Heureusement ça existe : valgrind. Par exemple si je passe ton programme par valgrind il me dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ==4861== Invalid read of size 1
    ==4861==    at 0x4E88C80: vfprintf (vfprintf.c:1632)
    ==4861==    by 0x4E8F848: printf (printf.c:33)
    ==4861==    by 0x40062B: main (fr.c:17)
    ==4861==  Address 0x5203040 is 0 bytes inside a block of size 4 free'd
    ==4861==    at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4861==    by 0x400615: main (fr.c:16)
    ==4861==  Block was alloc'd at
    ==4861==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4861==    by 0x4005C7: main (fr.c:8)
    Ce qui en clair donne : accès invalide en lecture à la ligne 17 de main à un bloc qui a déjà été libéré en ligne 16 et qui a été alloué en ligne 8.
    Sympa non ?

    Il y a une autre méthode un poil plus compliquée : l'address sanitizer. Comme je suppose que tu es à 42, que le compilo est de toute façon clang tu peux essayer un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ clang -Wall -Wextra -g3 -fsanitize=address -fno-omit-frame-pointer -o fr fr.c
    $ ASAN_SYMBOLIZER_PATH=`which llvm-symbolizer` ./fr
    La sortie est un peu plus cryptique, la commande à lancer pour récupérer les symboles plus compliquée mais ça donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    =================================================================
    ==5104==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000eff0 at pc 0x00000045fb56 bp 0x7ffda7e919b0 sp 0x7ffda7e91160
    READ of size 2 at 0x60200000eff0 thread T0
        #0 0x45fb55 in printf_common(void*, char const*, __va_list_tag*) (/...path.../fr+0x45fb55)
        #1 0x45f452 in printf_common(void*, char const*, __va_list_tag*) (/...path.../fr+0x45f452)
        #2 0x4601ca in __interceptor_vprintf (/...path.../fr+0x4601ca)
        #3 0x460287 in printf (/...path.../fr+0x460287)
        #4 0x4e9591 in main /...path.../fr.c:17:2
        #5 0x7f6f1d00082f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291
        #6 0x417db8 in _start (/...path.../fr+0x417db8)
     
    0x60200000eff0 is located 0 bytes inside of 4-byte region [0x60200000eff0,0x60200000eff4)
    freed by thread T0 here:
        #0 0x4b7d60 in __interceptor_cfree.localalias.0 (/...path.../fr+0x4b7d60)
        #1 0x4e957c in main /...path.../fr.c:16:2
        #2 0x7f6f1d00082f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291
     
    previously allocated by thread T0 here:
        #0 0x4b7ee8 in __interceptor_malloc (/...path.../fr+0x4b7ee8)
        #1 0x4e942a in main /...path.../fr.c:8:8
        #2 0x7f6f1d00082f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291
     
    SUMMARY: AddressSanitizer: heap-use-after-free (/...path.../fr+0x45fb55) in printf_common(void*, char const*, __va_list_tag*)
    Shadow bytes around the buggy address:
      0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    =>0x0c047fff9df0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fd]fa
      0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07 
      Heap left redzone:       fa
      Heap right redzone:      fb
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack partial redzone:   f4
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==5104==ABORTING

Discussions similaires

  1. session_start en premier ne fonctionne pas chez free
    Par aprosper dans le forum Langage
    Réponses: 4
    Dernier message: 12/09/2013, 11h49
  2. [.htaccess] AddType ne fonctionne pas chez Free
    Par toufou dans le forum Free
    Réponses: 4
    Dernier message: 28/11/2010, 12h54
  3. Pseudo Frame sur Free ne fonctionne pas
    Par tyler94 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 8
    Dernier message: 12/05/2009, 13h43
  4. Un Hint sur un PopupMenu ne fonctionne pas !!??
    Par momox dans le forum C++Builder
    Réponses: 6
    Dernier message: 26/05/2003, 16h48
  5. ca ne fonctionne pas (generateur auto-incrémentant)
    Par tripper.dim dans le forum SQL
    Réponses: 7
    Dernier message: 26/11/2002, 00h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo