Status: New
Owner: ----
Labels: Type-Defect Priority-Medium
New issue 166 by zhuizhuhaomeng: Ugly do_slabs_free
http://code.google.com/p/memcached/issues/detail?id=166
What steps will reproduce the problem?
static void do_slabs_free(void *ptr, const size_t size, unsigned int id) {
...
if (p->sl_curr == p->sl_total) { /* need more space on the free list */
int new_size = (p->sl_total != 0) ? p->sl_total * 2 : 16; /* 16 is
arbitrary */
void **new_slots = realloc(p->slots, new_size * sizeof(void *));
if (new_slots == 0)
return;
p->slots = new_slots;
p->sl_total = new_size;
}
According to this function, we know that, in order to maintain the free
item, we should allocate a new memory. Actually it is unnecessary and while
the realloc failed, do_slabs_free will cause memory leak.
What is the expected output? What do you see instead?
I fix the problem just as below. For the complete, please look at the
attachment.
1.
/* powers-of-N allocation structures */
typedef struct {
unsigned int size; /* sizes of items */
unsigned int perslab; /* how many items per slab */
item *free_item_list; /* a list of free item */
void *end_page_ptr; /* pointer to next free item at end of
page, or 0 */
unsigned int end_page_free; /* number of items remaining at end of last
alloced page */
unsigned int slabs; /* how many slabs were allocated for this class
*/
void **slab_list; /* array of slab pointers */
unsigned int list_size; /* size of prev array */
unsigned int killing; /* index+1 of dying slab, or zero if none */
size_t requested; /* The number of requested bytes */
} slabclass_t;
2.
static void *do_slabs_alloc(const size_t size, unsigned int id) {
/* fail unless we have space at the end of a recently allocated page,
we have something on our freelist, or we could allocate a new page */
if (! (p->end_page_ptr != 0 || p->free_item_list != NULL ||
do_slabs_newslab(id) != 0)) {
/* We don't have more memory available */
ret = NULL;
} else if (p->free_item_list != NULL) {
/* return off our freelist */
ret = p->free_item_list;
p->free_item_list = p->free_item_list->next;
} else {
3. do_slabs_free
static void do_slabs_free(item *ptr, const size_t size, unsigned int id) {
slabclass_t *p;
assert(ptr->slabs_clsid == 0);
assert(id >= POWER_SMALLEST && id <= power_largest);
if (id < POWER_SMALLEST || id > power_largest)
return;
MEMCACHED_SLABS_FREE(size, id, ptr);
p = &slabclass[id];
#ifdef USE_SYSTEM_MALLOC
mem_malloced -= size;
free(ptr);
return;
#endif
ptr->next = p->free_item_list;
p->free_item_list = ptr;
p->requested -= size;
return;
}
Attachments:
slabs.c 13.3 KB