2010-04-28 16 views
1

Dans glibc malloc.c ou dlmalloc Il a dit "repositionnement astuces" Comme dans blew, et d'utiliser cette astuce dans bin_at.bin_at dans dlmalloc

Les cases étant un tableau, l'espace est alloué lorsque av (struct malloc_state) est allouée. N'est-ce pas? le sizeof (bin [i]) est inférieur à sizeof (struct malloc_chunk *)? Lorsque bin_at (M, 1) (qui est utilisé comme unsorted_chunks) est appelé, le résultat est: bin [0] - offsetof (struct malloc_chunk, fd) bin [0] - 8 est correct?

Qui peut décrire cette astuce pour moi? Je ne peux pas comprendre la macro bin_at.why ils obtiennent l'adresse de bacs utiliser cette méthode? Comment cela fonctionne?

Merci beaucoup, et désolé pour mon mauvais anglais.

/* 
    To simplify use in double-linked lists, each bin header acts 
    as a malloc_chunk. This avoids special-casing for headers. 
    But to conserve space and improve locality, we allocate 
    only the fd/bk pointers of bins, and then use repositioning tricks 
    to treat these as the fields of a malloc_chunk*. 
*/ 

typedef struct malloc_chunk* mbinptr; 

/* addressing -- note that bin_at(0) does not exist */ 
#define bin_at(m, i) \ 
    (mbinptr) (((char *) &((m)->bins[((i) - 1) * 2]))    \ 
     - offsetof (struct malloc_chunk, fd)) 

La struct malloc_chunk comme ceci:

struct malloc_chunk { 

    INTERNAL_SIZE_T  prev_size; /* Size of previous chunk (if free). */ 
    INTERNAL_SIZE_T  size;  /* Size in bytes, including overhead. */ 

    struct malloc_chunk* fd;   /* double links -- used only if free. */ 
    struct malloc_chunk* bk; 

    /* Only used for large blocks: pointer to next larger size. */ 
    struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */ 
    struct malloc_chunk* bk_nextsize; 
}; 

Et le type de bac comme celui-ci:

typedef struct malloc_chunk* mbinptr; 

struct malloc_state { 
    /* Serialize access. */ 
    mutex_t mutex; 

    /* Flags (formerly in max_fast). */ 
    int flags; 

#if THREAD_STATS 
    /* Statistics for locking. Only used if THREAD_STATS is defined. */ 
    long stat_lock_direct, stat_lock_loop, stat_lock_wait; 
#endif 

    /* Fastbins */ 
    mfastbinptr  fastbinsY[NFASTBINS]; 

    /* Base of the topmost chunk -- not otherwise kept in a bin */ 
    mchunkptr  top; 

    /* The remainder from the most recent split of a small request */ 
    mchunkptr  last_remainder; 

    /* Normal bins packed as described above */ 
    mchunkptr  bins[NBINS * 2 - 2]; 

    /* Bitmap of bins */ 
    unsigned int  binmap[BINMAPSIZE]; 

    /* Linked list */ 
    struct malloc_state *next; 

#ifdef PER_THREAD 
    /* Linked list for free arenas. */ 
    struct malloc_state *next_free; 
#endif 

    /* Memory allocated from the system in this arena. */ 
    INTERNAL_SIZE_T system_mem; 
    INTERNAL_SIZE_T max_system_mem; 
}; 

Répondre

3

On peut supposer que struct malloc_chunk ressemble à quelque chose comme:

struct malloc_chunk { 
    /* ... fields here ... */ 
    struct malloc_chunk *fd; 
    struct malloc_chunk *bk; 
    /* ... more fields here ... */ 
}; 

... et leTyperessemble:

struct { 
    struct malloc_chunk *fd; 
    struct malloc_chunk *bk; 
}; 

La macro bin_at fait un pointeur sur la dernière structure en un pointeur faux à l'ancienne structure, dans le but d'accéder aux seuls les membres fd et bk (car ils sont les seuls qui existent dans le plus petit). à-dire bin_at(m, i)->fd et bin_at(m, i)->bk sont les mêmes que m->bins[(i - 1) * 2].fd et m->bins[(i - 1) * 2].bk, mais bin_at peuvent être utilisés dans des endroits qui attendent une struct malloc_chunk * (aussi longtemps qu'ils utilisent uniquement les membres fd et bk).

C'est un peu un hack. Je ne ferais pas cela dans votre propre code - rappelez-vous les conseils de Kernighan sur le code écrit aussi intelligemment que possible:

« Debugging est deux fois plus dur que l'écriture le code en premier lieu Par conséquent, si vous écrivez. le code comme intelligemment que possible, vous êtes, par définition , pas assez intelligent pour déboguer il. " - Brian W. Kernighan


OK, donc ->bins est pas un tableau de struct du tout - c'est un tableau de struct malloc_chunk *.

Notez que ->bins[(i - 1) * 2] fait référence aux i-ème paire de struct malloc_chunk * pointeurs dans le tableau ->bins.Cette paire est équivalente aux et bk paire de pointeurs dans un struct malloc_chunk, le premier (->bins[(i - 1) * 2]) étant équivalent à fd (ils auraient pu faire à la place ->bins un tableau de la plus petite structure suggérée ci-dessus, il serait fonctionnellement équivalent et probablement plus clair).

La macro bin_at permet l'insertion de code une de ces paires de pointeurs qui sont dans le tableau ->bins dans une liste chaînée de struct malloc_chunk struct - sans allouer un struct malloc_chunk entier. C'est l'économie d'espace dont ils parlent.

La bin_at macro prend un index dans le tableau bins, alors ne « si ce pointeur était en fait la valeur fd dans un struct malloc_chunk, puis calculer un pointeur vers où que struct malloc_chunk serait ». Il le fait en soustrayant le décalage du membre fd dans un struct malloc_chunk à partir de l'adresse de l'élément dans le tableau bins.

Il ne "localise pas vraiment le bins[i]" - c'est simple (&bins[i]). En fait, il localise le imaginairestruct malloc_chunk que bins[i] est le fd membre de. Désolé, c'est compliqué à expliquer parce que c'est un concept compliqué.

+0

Merci beaucoup pour votre réponse. Mais je ne sais toujours pas comment cela peut économiser de l'espace, et comment il trouve la poubelle [i]. J'ai édité la question et j'ai collé un peu plus de code. Pourriez-vous le décrire en détail? – chunhui

+0

Je pense que je le comprends.Merci beaucoup! – chunhui