Répondre à la discussion
Affichage des résultats 1 à 18 sur 18

allocation dynamique C



  1. #1
    Jack
    Modérateur

    allocation dynamique C


    ------

    Salut à tous.

    Le fil qui parle de pointeur, malloc, toussa, m'a titillé et j'ai voulu faire une petite expérience:
    Code:
    int main(){
    	int* p;
    	p = (int*)malloc(sizeof(int));
    	*p = 5;
    	printf("p=%d\n",*p);
    	free(p);
    	printf("p=%d\n",*p);
    	return 0;
    }
    j'utilise un compilateur C++, mais le problème doit être identique en C.
    Après le free(p), mon debugger montre que p possède toujours la même adresse. Comme le processus ne fait rien d'autre ensuite, le tas ne devrait pas être affecté. Et pourtant, le 2ème printf ne m'affiche pas 5.
    Comment expliquez-vous çà?

    Merci pour vos suggestions.

    -----

  2. Publicité
  3. #2
    kwariz

    Re : allocation dynamique C

    D'après la norme, le comportement de ce programme est indéterminé. Le problème vient de "Comme le processus ne fait rien d'autre ensuite, le tas ne devrait pas être affecté.", en effet le gestionnaire de mémoire peut faire plein de truc à ton insu suivant les stratégies qu'il implémente. Cela peut aussi dépendre des options de compilations ... les causes sont nombreuses.
    On peut imaginer par exemple que le gestionnaire de mémoire a demandé une page pour les petites alloc pour ton int, le free a libéré la page que l'OS par mesure de sécurité a remplit de 0 mais cette adresse reste toujours accessible ... bon c'est totalement imaginaire ...
    Il y a plusieurs gestionnaires différents avec des stratégies différentes (dlmalloc, jemalloc, ...).

  4. #3
    Jack
    Modérateur

    Re : allocation dynamique C

    D'après la norme, le comportement de ce programme est indéterminé.
    Exact. mais je voudrais comprendre ce qui se passe exactement.

    Chaque processus possédant son propre espace mémoire, personne d'autre que mon programme ne va toucher à la mémoire. Pourquoi du code serait-il généré pour mettre à 0 (en l'occurrence c'est 0xfeeefeee) cette mémoire. ce serait une dépense inutile.

    Bon, comme quelqu'un me l'a récemment rappelé dans mon entourage, ça relève de la sodomisation de diptère, mais c'est la curiosité qui l'emporte ici.

    A+

  5. #4
    Zartan

    Re : allocation dynamique C

    L'adresse contenue dans p a été libérée ce qui fait qu'elle est disponible pour la prochaine allocation mémoire avec les catastrophes qu'on peut imaginer.

    Comme c'est une erreur classique et qui est très difficile à détecter, les compilateurs modernes offrent des outils pour vérifier que les pointeurs ne sont pas utilisés après leur libération. Si vous affichez la valeur de p en hexadécimal il se peut que ça vous affiche quelque chose comme 0xDEADBEEF ou 0xDEADF00D.

    Si vous sortez du mode débogage l'adresse pointée par p ne changera probablement pas après free. C'est une des raisons qui font que les programmes plantent mystérieusement.
    Dernière modification par Zartan ; 20/10/2012 à 19h35.

  6. A voir en vidéo sur Futura
  7. #5
    Jack
    Modérateur

    Re : allocation dynamique C

    L'adresse contenue dans p a été libérée ce qui fait qu'elle est disponible pour la prochaine allocation mémoire avec les catastrophes qu'on peut imaginer.
    Ok, elle est libérée, j'ai bien compris. Je connais également tous ces problèmes, en particulier en multithreading, mais le fait est que la variable p possède le même contenu, donc pointe toujours au même endroit. Par conséquent *p devrait afficher la même chose les 2 fois.

    A+
    Dernière modification par Jack ; 20/10/2012 à 19h39.

  8. #6
    Zartan

    Re : allocation dynamique C

    C'est juste le mode debug qui fait ça.

    Code:
    int main(){
    	int* p;
    int* q;
    	p = (int*)malloc(sizeof(int));
    	*p = 5;
    	printf("p=%d\n",*p);
    	free(p);
            q = (int*)malloc(sizeof(int)); 
            *q = 7 ;
    	printf("p=%d\n",*p); // si q == p alors *p vaut 7
    	return 0;
    }
    Dernière modification par Zartan ; 20/10/2012 à 19h47.

  9. Publicité
  10. #7
    PA5CAL

    Re : allocation dynamique C

    Bonsoir

    Pour illustrer l'une des nombreuses possibilités évoquées par kwariz, chez moi (test gcc/win7, mode release) le début du bloc de mémoire libéré par free() est écrasé par le gestionnaire de mémoire (on y retrouve deux valeurs utilisées pour chaîner les blocs alloués).

  11. #8
    Zartan

    Re : allocation dynamique C


  12. #9
    kwariz

    Re : allocation dynamique C

    Citation Envoyé par Jack Voir le message
    Chaque processus possédant son propre espace mémoire, personne d'autre que mon programme ne va toucher à la mémoire. Pourquoi du code serait-il généré pour mettre à 0 (en l'occurrence c'est 0xfeeefeee) cette mémoire. ce serait une dépense inutile.
    Le gestionnaire de mémoire fait partie de ton programme, c'est lui qui demande à l'OS plus de mémoire. Si tu ne trouves plus la même valeur c;est que c'est lui qui l'a modifié.

  13. #10
    Jack
    Modérateur

    Re : allocation dynamique C

    Citation Envoyé par Zartan Voir le message
    C'est juste le mode debug qui fait ça.

    Code:
    int main(){
        int* p;
    int* q;
        p = (int*)malloc(sizeof(int));
        *p = 5;
        printf("p=%d\n",*p);
        free(p);
            q = (int*)malloc(sizeof(int)); 
            *q = 7 ;
        printf("p=%d\n",*p); // si q == p alors *p vaut 7
        return 0;
    }
    J'ai essayé mon code en release, en ligne de commande. 1er affichage: 5, 2ème: 2425028. Les valeurs sont toujours différentes.
    Avec ton code, *p ne vaut pas 7

    Pour illustrer l'une des nombreuses possibilités évoquées par kwariz, chez moi (test gcc/win7, mode release) le début du bloc de mémoire libéré par free() est écrasé par le gestionnaire de mémoire (on y retrouve deux valeurs utilisées pour chaîner les blocs alloués).
    Ce qui m'échappe apparemment, c'est pourquoi le gestionnaire de mémoire fait des écritures pour une libération pas free.

    FEEEFEEE Used by Microsoft's HeapFree() to mark freed heap memory
    bien vu. Mais pour moi la question reste entière. Quelle est l'intérêt de marquer cette mémoire? Lors d'un malloc, le gestionnaire de mémoire consulte une table qui tient à jour les blocs libres ou occupés du ta du processus. Pourquoi perdre du temps à lire le contenu de ces blocs alors?

    Le gestionnaire de mémoire fait partie de ton programme, c'est lui qui demande à l'OS plus de mémoire.
    Mon problème ne concerne pas la réservation de mémoire, mais sa libération.
    Si tu ne trouves plus la même valeur c;est que c'est lui qui l'a modifié.
    Pour quelle raison?

    A+

  14. #11
    kwariz

    Re : allocation dynamique C

    Citation Envoyé par Jack Voir le message
    ....
    Ce qui m'échappe apparemment, c'est pourquoi le gestionnaire de mémoire fait des écritures pour une libération pas free.
    ...
    bien vu. Mais pour moi la question reste entière. Quelle est l'intérêt de marquer cette mémoire? Lors d'un malloc, le gestionnaire de mémoire consulte une table qui tient à jour les blocs libres ou occupés du ta du processus. Pourquoi perdre du temps à lire le contenu de ces blocs alors?
    ...
    Mon problème ne concerne pas la réservation de mémoire, mais sa libération.
    Pour quelle raison?
    Tu fais l'hypothèse que "le gestionnaire de mémoire consulte une table ...". C'est une mauvaise hypothèse, le gestionnaire e mémoire fait bien plus, du moins dans son implémentation dans la gnu libc (par exemple). Je suppose que la msvcrt de microsoft utilise des stratégies similaires ...
    Les stratégie pour les petites, les moyennes et les grosses allocations sont très différentes.
    Par exemple, sur ma plateforme (linux 3.6 64bit, gcc 4.7. gnu libc 2.16) ton code légèrement modifié :
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
            int *p;
            int *q;
            p = (int *)malloc(sizeof(int));
            q = (int *)malloc(sizeof(int) * 2000);
            *p = 5;
            *q = 20;
            printf("p=%d\n", *p);
            printf("q=%d\n", *q);
            free(p);
            free(q);
            printf("p=%d\n", *p);
            printf("q=%d\n", *q);
            return 0;
    }
    donne :
    Code:
    > ./test_free
    p=5
    q=20
    p=0
    q=20
    Je suis curieux de connaître la sortie du même programme sous win ...
    Le gestionnaire de mémoire fait sa tambouille et je lui fais confiance pour avoir de bonnes performances. Ça ne me choque pas qu'il écrive des trucs dans certains cas. L'avantage avec l'open source est que si on veut vraiement savoir le pourquoi du comment on peut le faire.

  15. #12
    Jack
    Modérateur

    Re : allocation dynamique C

    Je suis curieux de connaître la sortie du même programme sous win ...
    p=5
    q=20
    p=4456644
    q=20

    Tu fais l'hypothèse que "le gestionnaire de mémoire consulte une table ...". C'est une mauvaise hypothèse, le gestionnaire e mémoire fait bien plus, du moins dans son implémentation dans la gnu libc (par exemple). Je suppose que la msvcrt de microsoft utilise des stratégies similaires ...
    Quand le parle du gestionnaire de mémoire, je parle de celui de l'OS. Les fonctions des librairies du C ne font que des requêtes à l'OS.

    Enfin bon, le comportement étant visiblement différent d'une plateforme à l'autre, ça va être difficile d'en tirer des conclusions. Le comportement étant non garanti car non prévu par la norme, ça n'est pas très grave.

    A+

    A+

  16. Publicité
  17. #13
    PA5CAL

    Re : allocation dynamique C

    Citation Envoyé par Jack Voir le message
    Ce qui m'échappe apparemment, c'est pourquoi le gestionnaire de mémoire fait des écritures pour une libération pas free.
    Le gestionnaire de mémoire doit écrire une information pour faire état de la libération du bloc alloué. Et comme assez souvent le système d'allocation des blocs de taille variable procède par l'entretien d'une liste chaînée, il est probable dans le cas que j'ai cité (car je ne suis pas rentré dans les détails pour vérifier), que c'est le « pied » de cette liste qui a écrasé le début du dernier bloc libéré par free().

    J'ai réitéré le test sur une config gcc/Mac, et si le bloc libéré est encore écrasé, il semble que ce ne soit pas par une information de même nature.

    Citation Envoyé par Jack Voir le message
    Quelle est l'intérêt de marquer cette mémoire? Lors d'un malloc, le gestionnaire de mémoire consulte une table qui tient à jour les blocs libres ou occupés du ta du processus. Pourquoi perdre du temps à lire le contenu de ces blocs alors?
    Comme je l'ai suggéré juste au-dessus, le plus souvent la gestion de la mémoire ne se fait pas à l'aide d'une table (dont la détermination de la taille poserait quelques difficultés), mais plutôt à l'aide d'une liste chaînée dont les éléments partagent le tas avec les blocs alloués par l'utilisateur.

    L'intérêt de marquer la mémoire libérée peut être de fournir un indicateur sur l'état libre du bloc, et de permettre dans une certaine mesure au gestionnaire de détecter si des données qui lui sont réservées (pointeur de la liste chaînée ou bloc non alloué) ont été écrasées par l'utilisateur.
    Dernière modification par PA5CAL ; 21/10/2012 à 00h45.

  18. #14
    PA5CAL

    Re : allocation dynamique C

    Pour info, on trouve par ici un petit laïus (condensé de celui indiqué par kwariz) sur l'allocation mémoire via glibc.
    Dernière modification par PA5CAL ; 21/10/2012 à 00h53.

  19. #15
    Zartan

    Re : allocation dynamique C

    Citation Envoyé par Jack Voir le message
    J'ai essayé mon code en release, en ligne de commande. 1er affichage: 5, 2ème: 2425028. Les valeurs sont toujours différentes.
    Avec ton code, *p ne vaut pas 7
    C'est possible, dans le temps ça se passait comme ça. Les gestionnaires d'allocation mémoire ont différentes stratégies.

    Mais pour moi la question reste entière. Quelle est l'intérêt de marquer cette mémoire?
    D'après la doc de MungWall (un utilitaire de débogage Amiga de l'époque) c'est pour "encourager les programmes à crasher"

    - Except when Enforcer is running, location 0 is set to $C0DEDBAD, i.e.
    programs referencing location zero will not f.e. find a null string.

    - On startup all free memory is munged with $ABADCAFE. If this number
    shows up, someone is referencing memory in the free list.

    - Except when MEMF_CLEAR is set, memory is pre-munged on allocation with
    $DEADFOOD. When this is used in an Enforcer report, the caller is
    allocating memory and doesn't initialize it before using it. Note that
    only memory which has a cookie attached will be pre-munged.

    - Memory is filled with $DEADBEEF before it is freed, encouraging
    programs reusing free'ed memory to crash.
    http://www.memphisamigagroup.net/dis...l/MungWall.doc

  20. #16
    Zartan

    Re : allocation dynamique C

    pour info je viens d'essayer avec gcc sous mac j'ai bien p=5 puis p=7

  21. #17
    Jack
    Modérateur

    Re : allocation dynamique C

    On est bien d'accord: le comportement n'est pas déterministe puisque non défini dans la norme.

    A+

  22. #18
    PA5CAL

    Re : allocation dynamique C

    Citation Envoyé par Jack Voir le message
    On est bien d'accord: le comportement n'est pas déterministe puisque non défini dans la norme.
    D'un autre côté, c'est sans surprise. Le langage C définit tout ce qui concerne le fonctionnement du programme, mais pas ce qu'il advient des ressources qu'il n'utilise pas ou qu'il n'utilise plus, lesquelles ne concernent que le système.

    Il en va du tas comme de la pile : quand la mémoire est rendue par le programme (libération de bloc pour le tas, retour de fonction pour les variables locales), ce dernier ne doit plus l'utiliser (... à moins d'avoir une idée précise et exacte de ce qui se passe derrière, et d'avoir expressément conçu le programme dans ce sens).
    Dernière modification par PA5CAL ; 21/10/2012 à 10h29.

  23. Publicité

Discussions similaires

  1. Allocation dynamique
    Par Titoune971 dans le forum Programmation et langages, Algorithmique
    Réponses: 16
    Dernier message: 03/02/2011, 16h43
  2. problème insertion fichier .txt dans une allocation dynamique
    Par Ptitsuisse91 dans le forum Programmation et langages, Algorithmique
    Réponses: 9
    Dernier message: 09/01/2011, 18h32
  3. allocation dynamique c/c++
    Par Lt972 dans le forum Logiciel - Software - Open Source
    Réponses: 2
    Dernier message: 16/06/2008, 13h19
  4. Dérogation Allocation de Recherche
    Par Reace dans le forum Orientation après le BAC
    Réponses: 6
    Dernier message: 11/12/2007, 15h58
  5. Allocation de recherche INSERM
    Par Cessounette dans le forum Orientation après le BAC
    Réponses: 10
    Dernier message: 14/09/2007, 09h43