?? cl_malloc.c
字號:
/* $Id: cl_malloc.c,v 1.11 2005/02/17 15:49:50 alan Exp $ */#include <portability.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#ifndef BSD#ifdef HAVE_MALLOC_H# include <malloc.h>#endif#endif#include <clplumbing/cl_malloc.h>#include <clplumbing/cl_log.h>#include <ltdl.h>static volatile cl_mem_stats_t * memstats = NULL;/* * Compile time malloc debugging switches: * * MARK_PRISTINE - puts known byte pattern in freed memory * Good at finding "use after free" cases * Cheap in memory, but expensive in CPU * * MAKE_GUARD - puts a known pattern *after* allocated memory * Good at finding overrun problems after the fact * Cheap in CPU, adds a few bytes to each malloc item * */#define MARK_PRISTINE 1 /* Expensive in CPU time */#define MAKE_GUARD 1 /* Adds 'n' bytes memory - cheap in CPU*/#define USE_ASSERTS 1#define DUMPONERR 1#ifndef DUMPONERR# define DUMPIFASKED() /* nothing */#else# define DUMPIFASKED() {abort();}#endif/* * * Malloc wrapper functions * * I wrote these so we can better track memory leaks, etc. and verify * that the system is stable in terms of memory usage. * * For our purposes, these functions are a somewhat faster than using * malloc directly (although they use a bit more memory) * * The general strategy is loosely related to the buddy system, * except very simple, well-suited to our continuous running * nature, and the constancy of the requests and messages. * * We keep an array of linked lists, each for a different size * buffer. If we need a buffer larger than the largest one provided * by the list, we go directly to malloc. * * Otherwise, we keep return them to the appropriate linked list * when we're done with them, and reuse them from the list. * * We never coalesce buffers on our lists, and we never free them. * * It's very simple. We get usage stats. It makes me happy. * * * Copyright (C) 2000 Alan Robertson <alanr@unix.sh> * * This software licensed under the GNU LGPL. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#define HA_MALLOC_MAGIC 0xFEEDBEEFUL#define HA_FREE_MAGIC 0xDEADBEEFUL/* * We put a struct cl_mhdr in front of every malloc item. * This means each malloc item is 12 bytes bigger than it theoretically * needs to be. But, it allows this code to be fast and recognize * multiple free attempts, and memory corruption *before* the object * * It's probably possible to combine these fields a bit, * since bucket and reqsize are only needed for allocated items, * both are bounded in value, and fairly strong integrity checks apply * to them. But then we wouldn't be able to tell *quite* as reliably * if someone gave us an item to free that we didn't allocate... * * Could even make the bucket and reqsize objects into 16-bit ints... * * The idea of getting it all down into 32-bits of overhead is * an interesting thought... */struct cl_mhdr {# ifdef HA_MALLOC_MAGIC unsigned long magic; /* Must match HA_*_MAGIC */#endif size_t reqsize; int bucket;};struct cl_bucket { struct cl_mhdr hdr; struct cl_bucket * next;};#define NUMBUCKS 8#define NOBUCKET (NUMBUCKS)static struct cl_bucket* cl_malloc_buckets[NUMBUCKS];static size_t cl_bucket_sizes[NUMBUCKS];static int cl_malloc_inityet = 0;static size_t cl_malloc_hdr_offset = sizeof(struct cl_mhdr);void* cl_malloc(size_t size);static void* cl_new_mem(size_t size, int numbuck);void* cl_calloc(size_t nmemb, size_t size);void cl_free(void *ptr);static void cl_malloc_init(void);static void cl_dump_item(const struct cl_bucket*b);#ifdef MARK_PRISTINE# define PRISTVALUE 0xff static int cl_check_is_pristine(const void* v, unsigned size); static void cl_mark_pristine(void* v, unsigned size); static int pristoff;#endif#define BHDR(p) ((struct cl_bucket*)(void*)(((char*)p)-cl_malloc_hdr_offset))#define CBHDR(p) ((const struct cl_bucket*)(const void*)(((const char*)p)-cl_malloc_hdr_offset))#define MEMORYSIZE(p)(CBHDR(p)->hdr.reqsize)#ifdef MAKE_GUARD# define GUARDLEN 4 static const unsigned char cl_malloc_guard[] =#if GUARDLEN == 1 {0xA5};#endif#if GUARDLEN == 2 {0x5A, 0xA5};#endif#if GUARDLEN == 4 {0x5A, 0xA5, 0x5A, 0xA5};#endif# define GUARDSIZE sizeof(cl_malloc_guard)# define ADD_GUARD(cp) (memcpy((((char*)cp)+MEMORYSIZE(cp)), cl_malloc_guard, sizeof(cl_malloc_guard)))# define GUARD_IS_OK(cp) (memcmp((((const char*)cp)+MEMORYSIZE(cp)), \ cl_malloc_guard, sizeof(cl_malloc_guard)) == 0)# define CHECK_GUARD_BYTES(cp, msg) { \ if (!GUARD_IS_OK(cp)) { \ cl_log(LOG_ERR, "%s: guard corrupted at 0x%lx", msg \ , (unsigned long)cp); \ cl_dump_item(CBHDR(cp)); \ DUMPIFASKED(); \ } \ }#else# define GUARDSIZE 0# define ADD_GUARD(cp) /* */# define GUARD_IS_OK(cp) (1)# define CHECK_GUARD_BYTES(cp, msg) /* */#endif/* * cl_malloc: malloc clone */void *cl_malloc(size_t size){ int j; int numbuck = NOBUCKET; struct cl_bucket* buckptr = NULL; void* ret; if (!cl_malloc_inityet) { cl_malloc_init(); } /* * Find which bucket would have buffers of the requested size */ for (j=0; j < NUMBUCKS; ++j) { if (size <= cl_bucket_sizes[j]) { numbuck = j; buckptr = cl_malloc_buckets[numbuck]; break; } } /* * Pull it out of the linked list of free buffers if we can... */ if (buckptr == NULL) { ret = cl_new_mem(size, numbuck); }else{ cl_malloc_buckets[numbuck] = buckptr->next; buckptr->hdr.reqsize = size; ret = (((char*)buckptr)+cl_malloc_hdr_offset); #ifdef MARK_PRISTINE { int bucksize = cl_bucket_sizes[numbuck]; if (!cl_check_is_pristine(ret, bucksize)) { cl_log(LOG_ERR , "attempt to allocate memory" " which is not pristine."); cl_dump_item(buckptr); DUMPIFASKED(); } }#endif#ifdef HA_MALLOC_MAGIC switch (buckptr->hdr.magic) { case HA_FREE_MAGIC: break; case HA_MALLOC_MAGIC: cl_log(LOG_ERR , "attempt to allocate memory" " already allocated at 0x%lx" , (unsigned long)ret); cl_dump_item(buckptr); DUMPIFASKED(); ret=NULL; break; default: cl_log(LOG_ERR , "corrupt malloc buffer at 0x%lx" , (unsigned long)ret); cl_dump_item(buckptr); DUMPIFASKED(); ret=NULL; break; } buckptr->hdr.magic = HA_MALLOC_MAGIC;#endif /* HA_MALLOC_MAGIC */ if (memstats) { memstats->nbytes_req += size; memstats->nbytes_alloc+=cl_bucket_sizes[numbuck]; } } if (ret && memstats) {#ifdef HAVE_MALLINFO struct mallinfo i = mallinfo(); memstats->arena = i.arena;#endif memstats->numalloc++; } if (ret) { ADD_GUARD(ret); } return(ret);}intcl_is_allocated(const void *ptr){#ifdef HA_MALLOC_MAGIC if (NULL == ptr || CBHDR(ptr)->hdr.magic != HA_MALLOC_MAGIC) { return FALSE; }else if (GUARD_IS_OK(ptr)) { return TRUE; } cl_log(LOG_ERR , "cl_is_allocated: supplied storage is guard-corrupted at 0x%lx" , (unsigned long)ptr); cl_dump_item(CBHDR(ptr)); DUMPIFASKED(); return FALSE;#else return (ptr != NULL);#endif}/* * cl_free: "free" clone */voidcl_free(void *ptr){ int bucket; struct cl_bucket* bhdr; if (!cl_malloc_inityet) { cl_malloc_init(); } if (ptr == NULL) { cl_log(LOG_ERR, "attempt to free NULL pointer in cl_free()"); DUMPIFASKED(); return; } /* Find the beginning of our "hidden" structure */ bhdr = BHDR(ptr);#ifdef HA_MALLOC_MAGIC switch (bhdr->hdr.magic) { case HA_MALLOC_MAGIC: break; case HA_FREE_MAGIC: cl_log(LOG_ERR , "cl_free: attempt to free already-freed" " object at 0x%lx" , (unsigned long)ptr); cl_dump_item(bhdr); DUMPIFASKED(); return; break; default: cl_log(LOG_ERR, "cl_free: Bad magic number" " in object at 0x%lx" , (unsigned long)ptr); cl_dump_item(bhdr); DUMPIFASKED(); return; break; }#endif if (!GUARD_IS_OK(ptr)) { cl_log(LOG_ERR , "cl_free: attempt to free guard-corrupted" " object at 0x%lx", (unsigned long)ptr); cl_dump_item(bhdr);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -