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

Affichage des résultats du sondage: Améliorer la bibliothèque standard au niveau de l'allocation dynamique?

Votants
10. Vous ne pouvez pas participer à ce sondage.
  • C'est une bonne idée

    1 10,00%
  • J'en vois pas l'utilité

    9 90,00%
C Discussion :

Allocation dynamique, discussion autour de la librairie standard


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 39
    Par défaut Allocation dynamique, discussion autour de la librairie standard
    Bonjour,

    Cette discussion viens en suite de celle-ci https://www.developpez.net/forums/d1...ire-d-origine/

    Résumé :

    Un code possible de realloc par @dalfab:
    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
    void *realloc( void *blocACopier , size_t nouvelleTaille ) {
       size_t  alloues = 0;     // bytes réservés
       size_t  taille = 0;      // bytes utilisables
       if ( blocACopier ) {
          alloues = ((size_t*)blocACopier)[-1]; // une structure possible ou une autre?
          taille  = ((size_t*)blocACopier)[-2];
          while ( nouvelleTaille > alloues  &&  la-zone-suivant-le-bloc-est-disponible ) {
             fusionner-le-bloc-avec-le-bloc-suivant-et-trouver-nouvelle-valeur-pour-'alloues'
             ((size_t*)blocACopier)[-1] = alloues;
          }
       }
       if ( nouvelleTaille > alloues ) {        // allocation nécessaire ailleurs
          void *tmp = malloc( nouvelleTaille ); //allocation d'une nouvelle zone mémoire et 2*size_t avant
          if ( !tmp ) return NULL;
          if ( blocAcopier ) {
             memcpy( tmp , blocACopier , taille );
             free( blocACopier );
             blocACopier = tmp;
          }
       }
       else { // assez ou trop grand
          if ( nouvelleTaille + TAILLE_HYSTERESIS < alloues ) { // trop grand
             couper-le-bloc-ne-garder-que-le-necessaire-et-trouver-nouvelle-valeur-pour-'alloues'
             ((size_t*)blocACopier)[-1] = alloues;
          }
          ((size_t*)blocACopier)[-2] = nouvelleTaille;  // noter la nouvelle taille utile
       }
       return blocACopier;
    }
    Pourquoi allez chercher les tailles d'allocation n'est pas standardisé?
    Citation Envoyé par @Jamatronic
    Pour interdire aux programmeurs d'aller consulter ces données et faire des bidouilles avec ?

    Si vous le faites, c'est à vos risques et périls.
    Citation Envoyé par @Médinoc
    Le fait est que le standard C ne prévoit aucun moyen de demander à l'implémentation la taille d'un bloc alloué. Choix délibéré ou oubli, je l'ignore.
    D'autres bibliothèques faisant de l'allocation de mémoire (comme les diverses de Windows) proposent de telles fonctions (LocalSize()/GlobalSize() pour LocalAlloc()/GlobalAlloc() (retournent la taille réelle du bloc, qui peut être plus grande que celle initialement demandée), HeapSize() pour HeapAlloc(), VirtualQuery() pour VirtualAlloc(), mais rien pour la mémoire allouée via CoTaskMemAlloc())

    Résultat, si tu fais un programme en C standard, c'est à toi de garder trace des tailles allouées (y compris, par exemple, en utilisant la tactique mentionnée par dalfab).
    Citation Envoyé par @Matt_Houston
    Quelle en serait l'utilité ? Ce serait imposer d'énormes contraintes au système d'allocation pour bien peu d'avantages offerts au programmeur au final.
    Citation Envoyé par @chrtophe
    malloc fonctionne sur des systèmes différents allant de Linux à MS-DOS. Il peut donc être logique que la façon dont la fonction gère l'allocation soit différente et qu'il ne faille pas "bricoler". C'est l'intérêt d'une fonction système, tu ne te préoccupe pas de son fonctionnement, tu lui donnes une (ou plusieurs) entrée(s) et tu attend un résultat en sortie.

    Tu peux toujours étudier le code source de la fonction.

    Ou plus facile d'accès un tuto comme celui-ci :
    http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf
    Fin du résumé.

    Je comprend que ce soit le système qui gère l'allocation, que les fonctions soit simplement un dialogue avec lui. Et son intérêt! Comme cela c'est adaptable sur tout support. Ce qui m'embête c'est que l'on est pas accès à tout. Obligé le programmeur à enregistrer lui même les tailles quand il en a besoin alors que le système le sais très bien c'est pas terrible... J'ai aussi découvert que la fonction recalloc n'existe pas. Bref c'est un manque que je trouve dommage.

    Je ne vois pas en quoi cela pourrait ajouter d'énormes contraintes au système d'allocation, vu qu'il a déjà l'air de le faire? Où que ce serait meilleur d'interdire les programmeurs de jouer avec...

    C'est pour cela que j'aimerai vous poser la question suivante : Est ce qu'une amélioration de la bibliothèque standard sur l'allocation dynamique serait une bonne chose? Offrir une plus grande liberté au programmeur et une meilleur interaction avec le système.

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Cela tient à la philosophie même du langage C: Celui-ci a été pensé pour la performance et pour offrir le maximum de liberté à l'implémentation. Ce qui soulève les problèmes suivants si on voulait rajouter une fonction getallocsize():
    • Pour des raisons de performance, d'alignement etc., la zone mémoire allouée peut être plus grande que la demande (par exemple, une taille arrondie aux 8 octets supérieurs). Quelle taille faudrait-il alors retourner? La vraie taille, comme le fait LocalSize() sous Windows, ou la taille demandée, comme le fait HeapSize?
    • Le premier cas peut poser des problèmes parce que malloc() n'initialise pas la mémoire qu'elle alloue, on risque donc un code qui demande X octets, les initialise, puis plus tard récupère la taille et croit que toute la zone est initialisée.
    • Le second cas oblige l'implémentation à mémoriser quelque part la taille demandée, qui peut être en plus de ses autres informations. D'où, utilisation de plus de mémoire pour chaque allocation, ralentissement de chaque allocation... malloc() est une fonction utilisée assez souvent pour que la performance puisse être un souci.

    Garder en mémoire la vraie taille demandée serait probablement moins gênant en C++, qui en a déjà besoin pour toutes les allocations de tableaux de types contenant un destructeur.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 39
    Par défaut
    Bonjour @Médinoc,

    Citation Envoyé par Médinoc
    Cela tient à la philosophie même du langage C: Celui-ci a été pensé pour la performance et pour offrir le maximum de liberté à l'implémentation. Ce qui soulève les problèmes suivants si on voulait rajouter une fonction getallocsize():

    Pour des raisons de performance, d'alignement etc., la zone mémoire allouée peut être plus grande que la demande (par exemple, une taille arrondie aux 8 octets supérieurs). Quelle taille faudrait-il alors retourner? La vraie taille, comme le fait LocalSize() sous Windows, ou la taille demandée, comme le fait HeapSize?
    Le premier cas peut poser des problèmes parce que malloc() n'initialise pas la mémoire qu'elle alloue, on risque donc un code qui demande X octets, les initialise, puis plus tard récupère la taille et croit que toute la zone est initialisée.
    Le second cas oblige l'implémentation à mémoriser quelque part la taille demandée, qui peut être en plus de ses autres informations. D'où, utilisation de plus de mémoire pour chaque allocation, ralentissement de chaque allocation... malloc() est une fonction utilisée assez souvent pour que la performance puisse être un souci.

    Garder en mémoire la vraie taille demandée serait probablement moins gênant en C++, qui en a déjà besoin pour toutes les allocations de tableaux de types contenant un destructeur.
    D'après les informations que j'ai pu récupéré dans ce post https://www.developpez.net/forums/d1...ire-d-origine/
    Ce tutoriel http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf et le code source de la glibc https://code.woboq.org/userspace/gli...l#_int_realloc

    Si j'ai bien compris c'est le second cas qui sera déjà utilisé.

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Précisons "qui est utilisé par la glibc dans la version que tu as étudiée."

  5. #5
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 551
    Par défaut
    Bonsoir,
    Il faut surtout comprendre que l’allocation dynamique d’une mémoire avec malloc() dépend du système et de l’architecture sur lequel elle est implémentée et chaque système d'exploitation apporte de légères adaptations à la fonction pour leur système (je parle de malloc() parce que, realloc() se base sur les sous-routines de malloc() ou malloc() lui-même). Il y a donc des variantes sur certaines sous-routines de malloc() (et je suis d'avis avec @chrtophe à ce propos). De plus, les choses sont bien plus compliquées en réalité que vous ne le pensez. Comme ce que vous avez pu en déduire de vos recherches, la fonction malloc() s'appuie sur deux routines sbrk() et mmap() (la projection mémoire) avec divers algorithmes pour l'allocation de la mémoire (stratégie d’allocation mémoire). malloc() donne également la possibilité au développeur d'invoquer leur propre fonction dans les routines de malloc() pour par exemple déboguer, optimiser, etc. grâce aux points d’appel.

    Citation Envoyé par dalfab Voir le message
    Bonjour,
    En fait malloc(), calloc() et realloc() allouent au moins 8 octets de plus que demandés, stockent dans ces octets les tailles allouées, et retournent un pointeur augmenté de 8. Le format de ces données n'est pas standardisé, c'est pourquoi on ne doit pas y accéder. Un code possible
    Non, pas tout à fait. L'exemple de l'allocation mémoire de plus se base sur sbrk() et c'est justifier. malloc() fait appel à sbrk() (occasionnellement car il gère dès le départ un semble de bloc mémoire), mais sollicite plus de mémoire non pas pour stocker les tailles allouées, mais tout simplement pour en fournir immédiatement lors d'un second appel de malloc() , car sbrk() en réalité coûte cher en ressources, mais elle renvoie bien la taille mémoire demander. (En ce qui concerne la taille en octet ; cela est lié l'architecture "les alignements". C'est-à-dire que malloc() garantit un alignement mémoire correct pour pouvoir stocker n'importe quel type de données. L'alignement de ces données est effectivement tous les 8 octets sur une architecture 32 bits et sur des architectures 64 bits elle est fixée à 16 octets et donc le format de ces données est bien standardisé parce que la taille utilisée par exemple sur une architecture 32 bits permet de manipuler directement des entiers voire réels dans la mémoire et qui d'ailleurs correspond à la taille d'un double ou d'un long long int).

    Citation Envoyé par Médinoc Voir le message
    C'est un détail d'implémentation et rien ne garantie que ce soit vraiment le cas (un OS pourrait stocker ses tailles quelque part en espace Kernel à la place, voire les déduires de ses listes chaînées de blocs...).


    Le fait est que le standard C ne prévoit aucun moyen de demander à l'implémentation la taille d'un bloc alloué. Choix délibéré ou oubli, je l'ignore.
    D'autres bibliothèques faisant de l'allocation de mémoire (comme les diverses de Windows) proposent de telles fonctions (LocalSize()/GlobalSize() pour LocalAlloc()/GlobalAlloc() (retournent la taille réelle du bloc, qui peut être plus grande que celle initialement demandée), HeapSize() pour HeapAlloc(), VirtualQuery() pour VirtualAlloc(), mais rien pour la mémoire allouée via CoTaskMemAlloc())
    Résultat, si tu fais un programme en C standard, c'est à toi de garder trace des tailles allouées (y compris, par exemple, en utilisant la tactique mentionnée par dalfab).
    GLibC, met à disposition un bon nombre de sous-routines, et même dédier au débogage exemple de quelque routine:
    • La fonction malloc_info() qui permet de fournir une chaîne XML qui décrit exactement l’état actuel de l'implémentation de l'allocation mémoire
    • La fonction mallopt() permet d'ajuster les paramètres qui contrôlent le comportement des fonctions d'allocation de mémoire
    • La fonction malloc_get_state() enregistre l'état actuel de tous les allocation (malloc) dans une variables internes mais pas le contenu réel du tas ou de l'état de ces mémoire.
    • La fonction malloc_set_state() est l'inverse de la précédente elle restaure l'état de tous les allocation.
    • La fonction malloc_trim() libère ou tente de libérer de la mémoire en haut du tas en appelant sbrk().
    • La fonction malloc_usable_size() renvoie le nombre d'octets utiliser dans le bloc pointé par ptr , un pointeur sur un bloc de mémoire alloué par malloc() realloc() etc.. en clair il permet obtenir la taille du bloc de mémoire alloué à partir de tas.
    • etc..


    Personnellement amélioré la bibliothèque standard au niveau de l'allocation dynamique, je ne vois pas vraiment l'intérêt, mais apporter quelque optimisation subtile pourquoi pas, mais cela demande à revoir pas mal de choses. Cependant, je ne suis pas contre votre première idée "un exemple d'utilisation des fonction de re-allocation" s'ils n'existent pas.
    À bientôt.

  6. #6
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 284
    Par défaut
    Je pense que les fonctions citées par Sambia sont spécifiques à glibc et pas POSIX. Ce qui signifie qu'elle ne seront pas valables sous FreeBSD par exemple.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

Discussions similaires

  1. Réponses: 3
    Dernier message: 15/06/2016, 06h27
  2. Extraire les objets d'une librairie dynamique
    Par Lapk_gre dans le forum C
    Réponses: 13
    Dernier message: 29/07/2008, 14h49
  3. Question sur les problèmes d'allocation dynamique
    Par slylafone dans le forum C++
    Réponses: 23
    Dernier message: 25/10/2004, 14h18
  4. Allocation dynamique de mémoire en asm
    Par narmataru dans le forum Assembleur
    Réponses: 7
    Dernier message: 17/12/2002, 22h31
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

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