1
votes

Gestion de la mémoire par malloc et gratuite

J'apprends actuellement comment la mémoire est gérée par malloc et libre, et je ne comprends pas pourquoi quand je veux malloc 1 octet, malloc allouera 32 octets pour le bloc? Pour moi, il devrait allouer 16 octets pour les métadonnées (taille du morceau précédent et du morceau suivant) et 1 octet pour les données ...

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/**                                                                                            
 * pmem - print mem                                                                            
 * @p: memory address to start printing from                                                   
 * @bytes: number of bytes to print                                                            
 *                                                                                             
 * Return: nothing                                                                             
 */
void pmem(void *p, unsigned int bytes)
{
    unsigned char *ptr;
    unsigned int i;

    ptr = (unsigned char *)p;
    for (i = 0; i < bytes; i++)
    {
        if (i != 0)
        {
            printf(" ");
        }
        printf("%02x", *(ptr + i));
    }
    printf("\n");
}

/**
 * main - moving the program break
 *
 * Return: EXIT_FAILURE if something failed. Otherwise EXIT_SUCCESS
 */
int main(void)
{
    void *p;
    size_t size_of_the_chunk;
    char prev_used;

    p = malloc(1);
    printf("%p\n", p);
    pmem((char *)p - 0x10, 0x10);
    size_of_the_chunk = *((size_t *)((char *)p - 8));
    prev_used = size_of_the_chunk & 1;
    size_of_the_chunk -= prev_used;
    printf("chunk size = %li bytes\n", size_of_the_chunk);
    return (EXIT_SUCCESS);
}

Voilà le résultat:

0x13bf010

00 00 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00

taille du bloc = 32 octets


3 commentaires

Comment vérifiez-vous? Veuillez créer un exemple minimal reproductible pour nous le montrer.


votre programme invoque un comportement indéfini.


Puisque vous posez des questions sur les détails d'implémentation, vous devez être très précis sur des éléments tels que votre système d'exploitation, votre bibliothèque C, les versions du système d'exploitation et la bibliothèque C.


4 Réponses :


1
votes

En bref, la gestion de la mémoire de la bibliothèque C est libre d'allouer autant de mémoire qu'elle le juge utile. Peut-être par souci de simplicité, il n'alloue que par multiples de 32 octets. Alors, évidemment, 32 octets est le minimum.

D'autres allocateurs peuvent utiliser d'autres stratégies.


0 commentaires

2
votes

Je veux malloc 1 octet, malloc allouera 32 octets pour le morceau? Pour moi, il devrait allouer 16 octets pour les métadonnées (taille du précédent morceau et morceau suivant) et 1 octet pour les données ...

Ensuite, vous devez écrire votre propre version du malloc .

Standard ne dit pas à quoi devrait ressembler cette allocation, s'il y a des données supplémentaires ou combien de mémoire sera allouée.

De nombreuses circonstances doivent être prises en considération, pas seulement les "métadonnées". Bien sûr, l'auteur de l'implémentation avait quelque chose en tête lorsqu'il a décidé de la manière d'implémenter 'malloc'


0 commentaires

5
votes

malloc est nécessaire pour renvoyer des pointeurs suffisamment alignés pour stocker tout type de données, même les types de données qui ne peuvent pas tenir dans l'espace alloué. Cela signifie que si _Alignof (max_align_t) == 32 sur votre système, malloc (1) ne doit renvoyer que des pointeurs multiples de 32, même si vous demandez moins l'espace que cela. Un moyen simple pour l'implémentation de le faire est d'arrondir chaque allocation à un multiple de 32 dans ses données comptables internes, ce qui semble être ce que vous recherchez.

Cependant, la norme C vous interdit spécifiquement d'accéder à la mémoire même un seul octet au-delà de la fin de l'espace que vous avez demandé. Il vous interdit également spécifiquement d'accéder aux données comptables internes de malloc . Si vous exécutez votre programme sous un validateur d'accès mémoire comme valgrind ou ASan, il plantera.


4 commentaires

Ok, mais pourquoi le pointeur doit être suffisamment aligné et pourquoi malloc doit réfléchir à ce que l'utilisateur va mettre dans cette mémoire? Je pose cette question car je dois réimplémenter malloc et je ne saisis pas ce concept.


Si vous n'êtes pas familier avec le concept d'alignement d'adresses, vous devez le rechercher avant de continuer à essayer d'implémenter malloc. La règle du standard C est conçue pour que malloc n'ait pas besoin de penser à ce que l'appelant mettra en mémoire; il produit toujours une adresse utilisable pour tout. Les gens se demandent s'il est judicieux d'insister sur l'alignement max_align_t pour les allocations inférieures à sizeof (max_align_t) ; cela peut gaspiller beaucoup d'espace pour des programmes qui font beaucoup de petites allocations. Mais la règle est ce qu'elle est, du moins pour le moment.


Est-ce lié au fait que le processeur lit 32 octets à la fois?


C'est lié à ça, oui. Je dois vraiment vous demander de faire vos propres recherches sur ce sujet - je ne peux pas insérer une explication complète de l'alignement dans la zone de commentaire et je suis sûr qu'il y a déjà de bonnes explications à ce sujet en ligne. Je chercherais quelques-uns pour vous, mais je suis sur le wifi vraiment peu fiable du café en ce moment.



0
votes

Pour moi, il devrait allouer 16 octets pour les métadonnées (taille du morceau précédent et du morceau suivant)

Non, vous ne pouvez pas dire quelque chose comme ça. Il devrait allouer au moins un octet, c'est tout. Vous supposez qu'une stratégie / implémentation d'allocation donnée fonctionne d'une manière très spécifique, mais vous ne pouvez pas en général. Il n'y a pas de norme qui spécifie la manière dont les blocs de mémoire libres / alloués sont gérés. Cela peut être décrit dans la documentation de la bibliothèque d'allocation que vous utilisez.

et 1 octet pour les données

Encore une fois, au moins. La plupart des allocateurs préfèrent allouer un tas d'octets (32 ou 64 est courant).


0 commentaires