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

📄 cl_malloc.c

📁 linux集群服务器软件代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $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 + -