Question

J'ai ce morceau de code

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int main(){
    void *a, *b;

    a = malloc(16);
    b = malloc(16);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);

    a = malloc(1024);
    b = malloc(1024);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);  
}

Ne devrait-il pas imprimer la dernière taille de bloc allouée (16 ou 1024)? Au lieu de cela, il imprime 24 et 1032, de sorte que la quantité de mémoire allouée semble avoir 8 octets supplémentaires.

Mon problème est (avant de créer ce scénario de test) que je fais malloc() dans une fonction (1024 octets) et renvoie le résultat attribué. En vérifiant la taille des blocs sur la fonction return, je reçois 516 blocs ... et je ne comprends pas pourquoi. Je suppose que cela pourrait être la raison de la corruption de mémoire qui se produit après un traitement sur les tampons alloués:)

Modifier: j'ai vu comment obtenir la taille d'un tableau à partir d'un pointeur en C? et semble demander la même chose, désolée pour le repostage.

J'ai refait mon exemple avec mon code plus spécifique:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

short int * mallocStuff(long int number, short int base){
    short int *array;
    int size=1024;

    array=(short int*)calloc(1,size);
    //array=(short int*)malloc(size);

    return array;
}

int main(){
    short int **translatedArray;

    translatedArray=malloc(4*sizeof(short int));

    int i;
    for(i=0;i<4;i++){
        translatedArray[i]=mallocStuff(0,0);

        if(i>0)
            printf("\n   block size (for a): %p-%p : %i",
                translatedArray[i], translatedArray[i-1], translatedArray[i]-translatedArray[i-1]);
    }

    return 0;
}

Et la sortie est

   block size (for a): 0x804a420-0x804a018 : 516
   block size (for a): 0x804a828-0x804a420 : 516
   block size (for a): 0x804ac30-0x804a828 : 516

Selon le message ci-dessus, il est supérieur à 1024. Est-ce que je me trompe?

Était-ce utile?

La solution

Vous avez un bug. Au lieu de:

translatedArray=malloc(4*sizeof(short int));

Vous devriez avoir

translatedArray=malloc(4*sizeof(short int*));

Notez le pointeur manquant dans votre code. Je soupçonne que votre comportement observé découle de cela.

Notez également que 0x804a420 - 0x804a018 = 1032 et non 516. La formule translatedArray[i] - translatedArray[i - 1] vous donne le nombre d'éléments (raccourcis ou plus simplement courts) entre les deux adresses, pas le nombre de octets .

Autres conseils

Premièrement, Malloc ne garantit pas que deux appels Malloc successifs renvoient des pointeurs successifs.

Deuxièmement, en fonction de votre architecture spécifique, différentes règles d'alignement s'appliquent. Parfois, vous pouvez demander un seul octet, mais l'architecture préfère les allocations sur des intervalles de 8 ou 4 octets.

Troisièmement, malloc a besoin de frais généraux pour stocker la taille du bloc alloué, etc.

Ne faites pas de suppositions sur ce que malloc fait après ce que dit la documentation!

La fonction malloc alloue toujours un peu plus que vous ne le souhaitez, afin de stocker certaines informations de comptabilité. Après tout, lorsque vous appelez free(), il doit savoir quelle est la taille du bloc.

De même, les short int implémentations arrondissent généralement la taille demandée au prochain multiple de 8 ou 16, ou à un autre chiffre arrondi.

Mettre à jour : la vraie réponse à votre question réside dans votre utilisation du type <=>. Lorsque vous effectuez une arithmétique de pointeur (soustraction) entre des pointeurs typés, C et C ++ renvoient la différence entre le nombre des éléments pointés. Puisque vous pointez sur <=>, qui a une taille de deux octets, la valeur renvoyée correspond à la moitié de ce que vous attendez.

D'un autre côté, <=> attribue toujours un nombre donné de octets , quel que soit le résultat de conversion du résultat. Essayez ceci:

    array=(short int*)malloc(sizeof(short int) * size);

Il n'y a aucune garantie que deux appels malloc renvoient des blocs parfaitement emballés - en fait, il n'y a aucune garantie quant au résultat, sauf que s'il n'est pas NULL, il indiquera un bloc aussi petit que celui-ci. demandé.

En interne, la plupart des mallocs conservent des données de travail pour les aider à gérer le tas. Par exemple, ces 8 octets peuvent contenir deux pointeurs - l'un pointant vers le bloc suivant et l'autre pointant vers le bloc précédent. Je ne sais pas ce que sont ces 8 octets parce que vous n’avez pas mentionné le système d’exploitation sur lequel vous travaillez, mais il est tout à fait normal que malloc utilise de la mémoire pour lui-même dans les coulisses.

Certains allocateurs (par exemple sur Windows) fournissent une fonction de bibliothèque permettant de découvrir la taille de bloc à partir d'un pointeur, mais d'autres non, car il s'agit d'une fonctionnalité plutôt ésotérique.

Le retour de malloc dépend de la mise en oeuvre de malloc et de son architecture. Comme d'autres l'ont déjà dit, vous êtes assuré d'obtenir au moins la quantité de mémoire demandée, ou NULL. C'est aussi pourquoi parfois, vous pouvez écrire au-delà de la fin d'un tableau et ne pas avoir d'erreur de segmentation. C’est parce que vous avez effectivement un accès valide à cette mémoire, mais vous ne le saviez pas.

malloc () est généralement implémenté en scindant le segment de mémoire disponible en morceaux de différentes tailles. Dans votre cas, malloc () renvoie 2 morceaux consécutifs de 1024 (ou 16) octets. L’espace de 8 octets que vous mentionnez est utilisé par malloc () pour les informations de tenue de livres.

Voir les notes impliquées dans malloc () de Doug Lea ici pour comprendre ce qui se passe dans les coulisses: http://g.oswego.edu/dl/html/malloc.html

malloc() aura ses propres frais généraux.

Sans compter que rien ne garantit que deux allocations consécutives seront côte à côte.

Si malloc renvoie un élément autre que null, la mémoire allouée pour votre programme a la taille que vous avez transmise à <=>. Prendre la différence de pointeur entre les valeurs de retour de deux appels de différence vers <=> pourrait avoir n'importe quelle valeur et n'a rien à faire (bien que peu) avec la taille de bloc du premier bloc alloué.

J'ai trouvé ceci..et vérifiez le lien ci-dessous pour plus d'informations.

Allocation

Un bloc est alloué à partir du pool libre en convertissant d'abord les octets demandés en un index dans le tableau à compartiments, à l'aide de l'équation suivante:

nécessaire = demandé + 8

Si nécessaire < = 16, puis seau = 0

Si nécessaire > 16 puis compartiment = (log (nécessaire) / log (2) arrondi au nombre entier le plus proche) - 3

La taille de chaque bloc de la liste ancrée par le compartiment est block size = 2 bucket + 4. Si la liste dans le compartiment est null, la mémoire est allouée à l'aide du sous-programme sbrk pour ajouter des blocs à la liste. Si la taille de bloc est inférieure à une page, une page est allouée à l'aide du sous-programme sbrk et le nombre de blocs obtenus en divisant la taille de bloc en taille de page est ajouté à la liste. Si la taille du bloc est égale ou supérieure à une page, la mémoire nécessaire est allouée à l'aide du sous-programme sbrk et un seul bloc est ajouté à la liste des disponibilités du compartiment. Si la liste disponible n'est pas vide, le bloc en tête de la liste est renvoyé à l'appelant. Le bloc suivant de la liste devient alors la nouvelle tête.

http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm

Avant le pointeur se trouve la taille du tableau suivant, qui est un entier 32/64 bits (ne sait pas si signé ou non signé)

la quantité de mémoire allouée semble donc avoir 8 octets supplémentaires? malloc() implémentée sur votre système semble allouer des octets supplémentaires pour conserver les informations de métadonnées, telles que la taille de la section de tas, adresse de départ, etc info.

Bien que cela varie sur différentes plates-formes. Sur mes systèmes X86, 17 allouer un minimum de malloc(0) octets, même si je demande <=>.

int main(void) {
    int *p = malloc(0);
    if(p == NULL) {
        /* error handling */
    }
    printf("%d\n",p[-1]);/ *it prints 17 bytes */
    /* some code */
    return 0;
}

malloc () peut allouer de la mémoire contiguë, mais lorsque vous appelez malloc () deux fois et que vous ne pouvez pas vous attendre à ce que la mémoire allouée soit contiguë en soustrayant deux pointeurs variés ...

Cependant, la mémoire allouée est une mémoire virtuelle qui fait partie de la mise en œuvre du noyau, la gestion de la mémoire (VFS) devant être spécifique. Cela pourrait ne pas affecter les fonctionnalités de l'application.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top