⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cl_malloc.c

📁 在LINUX下实现HA的源代码
💻 C
字号:
/* $Id: cl_malloc.c,v 1.1.2.4 2005/01/12 02:25:46 horms 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 * */#undef	MARK_PRISTINE		/* Expensive in CPU time */#define	MAKE_GUARD	1	/* Adds 4 bytes memory - cheap in CPU*//* * *	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(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 2	static const 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((((char*)cp)+MEMORYSIZE(cp)), cl_malloc_guard, sizeof(cl_malloc_guard)) == 0)#else#	define GUARDSIZE	0#	define ADD_GUARD(cp)	/* */#	define GUARD_IS_OK(cp)	(1)#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);			}		}#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);				ret=NULL;				break;			default:				cl_log(LOG_ERR				, "corrupt malloc buffer at 0x%lx"				,	(unsigned long)ret);				cl_dump_item(buckptr);				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	return (ptr && CBHDR(ptr)->hdr.magic == HA_MALLOC_MAGIC);#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()");		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);			return;			break;		default:			cl_log(LOG_ERR, "cl_free: Bad magic number"			" in object at 0x%lx"			,	(unsigned long)ptr);			cl_dump_item(bhdr);			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);		return;	}	bucket = bhdr->hdr.bucket;#ifdef HA_MALLOC_MAGIC	bhdr->hdr.magic = HA_FREE_MAGIC;#endif	/*	 * Return it to the appropriate bucket (linked list), or just free	 * it if it didn't come from one of our lists...	 */	if (bucket >= NUMBUCKS) {		if (memstats) {			if (memstats->nbytes_alloc >= bhdr->hdr.reqsize) {				memstats->nbytes_req   -= bhdr->hdr.reqsize;				memstats->nbytes_alloc -= bhdr->hdr.reqsize;				memstats->mallocbytes  -= bhdr->hdr.reqsize;			}		}		free(bhdr);	}else{		int	bucksize = cl_bucket_sizes[bucket];#if 0		ASSERT(bhdr->hdr.reqsize <= cl_bucket_sizes[bucket]);#endif		if (memstats) {			if (memstats->nbytes_alloc >= bhdr->hdr.reqsize) {				memstats->nbytes_req  -= bhdr->hdr.reqsize;				memstats->nbytes_alloc-= bucksize;			}		}		bhdr->next = cl_malloc_buckets[bucket];		cl_malloc_buckets[bucket] = bhdr;#ifdef MARK_PRISTINE		mark_pristine(ptr, bucksize);#endif	}	if (memstats) {		memstats->numfree++;	}}/* * cl_new_mem:	use the real malloc to allocate some new memory */static void*cl_new_mem(size_t size, int numbuck){	struct cl_bucket*	hdrret;	size_t			allocsize;	size_t			mallocsize;	if (numbuck < NUMBUCKS) {		allocsize = cl_bucket_sizes[numbuck];	}else{		allocsize = size;	}	mallocsize = allocsize + cl_malloc_hdr_offset + GUARDSIZE;	if ((hdrret = malloc(mallocsize)) == NULL) {		return NULL;	}	hdrret->hdr.reqsize = size;	hdrret->hdr.bucket = numbuck;#ifdef HA_MALLOC_MAGIC	hdrret->hdr.magic = HA_MALLOC_MAGIC;#endif	if (memstats) {		memstats->nbytes_alloc += mallocsize;		memstats->nbytes_req += size;		memstats->mallocbytes += mallocsize;	}	/* BEAM BUG -- this is NOT a leak */	return(((char*)hdrret)+cl_malloc_hdr_offset); /*memory leak*/}/* * cl_calloc: calloc clone */void *cl_calloc(size_t nmemb, size_t size){	void *	ret = cl_malloc(nmemb*size);	if (ret != NULL) {		memset(ret, 0, nmemb*size);	}			return(ret);}/* * cl_strdup: strdup clone */char *cl_strdup(const char *s){	void * ret = cl_malloc((strlen(s) + 1) * sizeof(char));	if (ret) {		strcpy(ret, s);	}			return(ret);}/* * cl_malloc_init():	initialize our malloc wrapper things */static voidcl_malloc_init(){	int	j;	size_t	cursize = 32;	cl_malloc_inityet = 1;	if (cl_malloc_hdr_offset < sizeof(long long)) {		cl_malloc_hdr_offset = sizeof(long long);	}	for (j=0; j < NUMBUCKS; ++j) {		cl_malloc_buckets[j] = NULL;		cl_bucket_sizes[j] = cursize;		cursize <<= 1;	}#ifdef MARK_PRISTINE	{		struct cl_bucket	b;		pristoff = (unsigned char*)&(b.next)-(unsigned char*)&b;		pristoff += sizeof(b.next);	}#endif}void cl_malloc_setstats(volatile cl_mem_stats_t *stats){	memstats = stats;}static voidcl_dump_item(struct cl_bucket*b){	unsigned char *	cbeg;	unsigned char *	cend;	unsigned char *	cp;	cl_log(LOG_INFO, "Dumping cl_malloc item @ 0x%lx, bucket address: 0x%lx"	,	((unsigned long)b)+cl_malloc_hdr_offset, (unsigned long)b);#ifdef HA_MALLOC_MAGIC	cl_log(LOG_INFO, "Magic number: 0x%lx reqsize=%ld"	", bucket=%d, bucksize=%ld"	,	b->hdr.magic	,	(long)b->hdr.reqsize, b->hdr.bucket	,	(long)(b->hdr.bucket >= NUMBUCKS ? 0 	:	cl_bucket_sizes[b->hdr.bucket]));#else	cl_log(LOG_INFO, "reqsize=%ld"	", bucket=%d, bucksize=%ld"	,	(long)b->hdr.reqsize, b->hdr.bucket	,	(long)(b->hdr.bucket >= NUMBUCKS ? 0 	:	cl_bucket_sizes[b->hdr.bucket]));#endif	cbeg = ((unsigned char *)b)+cl_malloc_hdr_offset;	cend = cbeg+b->hdr.reqsize+GUARDSIZE;	for (cp=cbeg; cp < cend; cp+= sizeof(unsigned)) {		cl_log(LOG_INFO, "%02x %02x %02x %02x \"%c%c%c%c\""		,	(unsigned)cp[0], (unsigned)cp[1]		,	(unsigned)cp[2], (unsigned)cp[3]		,	cp[0], cp[1], cp[2], cp[3]);	}}#ifdef MARK_PRISTINEstatic intcl_check_is_pristine(const void* v, unsigned size){	const unsigned char *	cp;	const unsigned char *	last;	cp = v;	last = cp + size;	cp += pristoff;	for (;cp < last; ++cp) {		if (*cp != PRISTVALUE) {			return FALSE;		}	}	return TRUE;}static voidcl_mark_pristine(void* v, unsigned size){	unsigned char *	cp = v;	memset(cp+pristoff, PRISTVALUE, size-pristoff);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -