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

📄 malloc.c

📁 对内存的分配、释放和使用进行检查
💻 C
字号:
/* * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).   * You may copy, distribute, and use this software as long as this * copyright statement is not removed. */#include <stdio.h>#include <fcntl.h>#include "malloc.h"#include "tostring.h"/* * Function:	malloc() * * Purpose:	memory allocator * * Arguments:	size	- size of data area needed * * Returns:	pointer to allocated area, or NULL if unable *		to allocate addtional data. * * Narrative: * */#ifndef lintstaticchar rcs_hdr[] = "$Id: malloc.c,v 1.6 90/05/11 00:13:09 cpcahil Exp $";#endifint		  malloc_checking;char		* malloc_data_start;char		* malloc_data_end;struct mlist 	* malloc_end;int		  malloc_errfd = 2;int		  malloc_errno;int		  malloc_fatal_level = M_HANDLE_CORE;struct mlist	  malloc_start;int		  malloc_warn_level;char *malloc(size)	unsigned int	  size;{	char		* func = "malloc";	char		* getenv();	void		  malloc_fatal();	void		  malloc_init();	void		  malloc_memset();	void		  malloc_split();	void		  malloc_warning();	unsigned int	  need;	struct mlist	* oldptr;	struct mlist	* ptr;	char		* sbrk();	/*	 * If this is the first call to malloc...	 */	if( malloc_data_start == (char *) 0 )	{		malloc_init();	}	/*	 * If malloc chain checking is on, go do it.	 */	if( malloc_checking )	{		(void) malloc_chain_check(1);	}	/*	 * always make sure there is at least on extra byte in the malloc	 * area so that we can verify that the user does not overrun the	 * data area.	 */	size++;	/*	 * Now look for a free area of memory of size bytes...	 */	oldptr = NULL;	for(ptr = &malloc_start; ; ptr = ptr->next)	{		/*		 * Since the malloc chain is a forward only chain, any		 * pointer that we get should always be positioned in 		 * memory following the previous pointer.  If this is not		 * so, we must have a corrupted chain.		 */		if( ptr )		{			if(ptr < oldptr )			{				malloc_errno = M_CODE_CHAIN_BROKE;				malloc_fatal(func);				return(NULL);			}			oldptr = ptr;		}		else if( oldptr != malloc_end )		{			/*			 * This should never happen.  If it does, then			 * we got a real problem.			 */			malloc_errno = M_CODE_NO_END;			malloc_fatal(func);			return(NULL);		}				/*		 * if this element is already in use...		 */		if( ptr && ((ptr->flag & M_INUSE) != 0) )		{			continue;		}		/*		 * if there isn't room for this block..		 */		if( ptr && (ptr->s.size < size) )		{			continue;		}		/*		 * If ptr is null, we have run out of memory and must sbrk more		 */		if( ptr == NULL )		{			need = (size + M_SIZE) * (size > 100*1024 ? 1:2);			if( need < M_BLOCKSIZE )			{				need = M_BLOCKSIZE;			}			else if( need & (M_BLOCKSIZE-1) )			{				need &= ~(M_BLOCKSIZE-1);				need += M_BLOCKSIZE;			}			ptr = (struct mlist *) sbrk((int)need);			if( ptr == (struct mlist *) -1 )			{				malloc_errno = M_CODE_NOMORE_MEM;				malloc_fatal(func);			}			malloc_data_end = sbrk((int)0);			ptr->prev   = oldptr;			ptr->next   = (struct mlist *) 0;			ptr->s.size = need - M_SIZE;			ptr->flag  = M_MAGIC;			oldptr->next = ptr;			malloc_end = ptr;		} /* if( ptr ==... */		/*	 	 * Now ptr points to a memory location that can store		 * this data, so lets go to work.		 */		ptr->r_size = size;		/* save requested size	*/		ptr->flag |= M_INUSE;		/*	 	 * split off unneeded data area in this block, if possible...		 */		malloc_split(ptr);		/*		 * re-adjust the requested size so that it is what the user		 * actually requested...		 */		ptr->r_size--;		/*		 * just to make sure that noone is misusing malloced	 	 * memory without initializing it, lets set it to		 * all '\01's.  We call local_memset() because memset()		 * may be checking for malloc'd ptrs and this isn't		 * a malloc'd ptr yet.		 */		malloc_memset(ptr->data,M_FILL,(int)ptr->s.size);		return( ptr->data);	} /* for(... */} /* malloc(... *//* * Function:	malloc_split() * * Purpose:	to split a malloc segment if there is enough room at the *		end of the segment that isn't being used * * Arguments:	ptr	- pointer to segment to split * * Returns:	nothing of any use. * * Narrative: *		get the needed size of the module * 		round the size up to appropriat boundry *		calculate amount of left over space *		if there is enough left over space *		    create new malloc block out of remainder *		    if next block is free  *			join the two blocks together *		    fill new empty block with free space filler * 		    re-adjust pointers and size of current malloc block *		 *		 * * Mod History:	 *   90/01/27	cpcahil		Initial revision. */voidmalloc_split(ptr)	struct mlist		* ptr;{	extern struct mlist	* malloc_end;	void			  malloc_join();	void			  malloc_memset();	int			  rest;	int			  size;	struct mlist		* tptr;	size = ptr->r_size;	/*	 * roundup size to the appropriate boundry	 */	M_ROUNDUP(size);	/*	 * figure out how much room is left in the array.	 * if there is enough room, create a new mlist 	 *     structure there.	 */	if( ptr->s.size > size )	{		rest = ptr->s.size - size;	}	else	{		rest = 0;	}		if( rest > (M_SIZE+M_RND) )	{		tptr = (struct mlist *) (ptr->data+size);		tptr->prev = ptr;		tptr->next = ptr->next;		tptr->flag = M_MAGIC;		tptr->s.size = rest - M_SIZE;		/*		 * If possible, join this segment with the next one		 */		malloc_join(tptr, tptr->next,0,0);		if( tptr->next )		{			tptr->next->prev = tptr;		}		malloc_memset(tptr->data,M_FREE_FILL, (int)tptr->s.size);		ptr->next = tptr;		ptr->s.size = size;		if( malloc_end == ptr )		{			malloc_end = tptr;		}	}} /* malloc_split(... *//* * Function:	malloc_join() * * Purpose:	to join two malloc segments together (if possible) * * Arguments:	ptr	- pointer to segment to join to. * 		nextptr	- pointer to next segment to join to ptr. * * Returns:	nothing of any values. * * Narrative: * * Mod History:	 *   90/01/27	cpcahil		Initial revision. */voidmalloc_join(ptr,nextptr, inuse_override, fill_flag)	struct mlist	* ptr;	struct mlist	* nextptr;	int		  inuse_override;	int		  fill_flag;{	unsigned int	  newsize;	if( 	ptr     && ! (inuse_override || (ptr->flag & M_INUSE)) && 		nextptr && ! (nextptr->flag & M_INUSE) &&		((ptr->data+ptr->s.size) == (char *) nextptr) )	{		if( malloc_end == nextptr )		{			malloc_end = ptr;		}		ptr->next = nextptr->next;		newsize = nextptr->s.size + M_SIZE;		/*		 * if we are to fill and this segment is in use,		 *   fill in with M_FILL newly added space...	 	 */		if(fill_flag && (ptr->flag & M_INUSE) )		{			malloc_memset(ptr->data+ptr->s.size,				      M_FILL, (int)(nextptr->s.size + M_SIZE));		}		ptr->s.size += newsize;		if( ptr->next )		{			ptr->next->prev = ptr;		}	}} /* malloc_join(... *//* * The following mess is just to ensure that the versions of these functions in * the current library are included (to make sure that we don't accidentaly get  * the libc versions. (This is the lazy man's -u ld directive) */void free();int strcmp();int memcmp();char	* realloc();void		(*malloc_void_funcs[])() ={	free,};int		(*malloc_int_funcs[])() ={	strcmp,	memcmp,};char		* (*malloc_char_star_funcs[])() ={	realloc,};/* * This is malloc's own memset which is used without checking the parameters. */voidmalloc_memset(ptr,byte,len)	char		* ptr;	char		  byte;	int		  len;{	while(len-- > 0)	{		*ptr++ = byte;	}} /* malloc_memset(... *//* * Function:	malloc_fatal() * * Purpose:	to display fatal error message and take approrpriate action * * Arguments:	funcname - name of function calling this routine * * Returns:	nothing of any value * * Narrative: * * Notes:	This routine does not make use of any libc functions to build *		and/or disply the error message.  This is due to the fact that *		we are probably at a point where malloc is having a real problem *		and we don't want to call any function that may use malloc. */voidmalloc_fatal(funcname)	char		* funcname;{	char		  errbuf[128];	void		  exit();	void		  malloc_err_handler();	extern char	* malloc_err_strings[];	extern int	  malloc_errno;	extern int	  malloc_fatal_level;	char		* s;	char		* t;	s = errbuf;	t = "Fatal error: ";	while( *s = *t++)	{		s++;	}	t = funcname;	while( *s = *t++)	{		s++;	}	t = "(): ";	while( *s = *t++)	{		s++;	}	t = malloc_err_strings[malloc_errno];	while( *s = *t++)	{		s++;	}	*(s++) = '\n';	if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))	{		(void) write(2,"I/O error to error file\n",(unsigned)24);		exit(110);	}	malloc_err_handler(malloc_fatal_level);} /* malloc_fatal(... *//* * Function:	malloc_warning() * * Purpose:	to display warning error message and take approrpriate action * * Arguments:	funcname - name of function calling this routine * * Returns:	nothing of any value * * Narrative: * * Notes:	This routine does not make use of any libc functions to build *		and/or disply the error message.  This is due to the fact that *		we are probably at a point where malloc is having a real problem *		and we don't want to call any function that may use malloc. */voidmalloc_warning(funcname)	char		* funcname;{	char		  errbuf[128];	void		  exit();	void		  malloc_err_handler();	extern char	* malloc_err_strings[];	extern int	  malloc_errno;	extern int	  malloc_warn_level;	char		* s;	char		* t;	s = errbuf;	t = "Warning: ";	while( *s = *t++)	{		s++;	}	t = funcname;	while( *s = *t++)	{		s++;	}	t = "(): ";	while( *s = *t++)	{		s++;	}	t = malloc_err_strings[malloc_errno];	while( *s = *t++)	{		s++;	}	*(s++) = '\n';	if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))	{		(void) write(2,"I/O error to error file\n",(unsigned)24);		exit(110);	}	malloc_err_handler(malloc_warn_level);} /* malloc_warning(... *//* * Function:	malloc_err_handler() * * Purpose:	to take the appropriate action for warning and/or fatal  *		error conditions. * * Arguments:	level - error handling level  * * Returns:	nothing of any value * * Narrative: * * Notes:	This routine does not make use of any libc functions to build *		and/or disply the error message.  This is due to the fact that *		we are probably at a point where malloc is having a real problem *		and we don't want to call any function that may use malloc. */voidmalloc_err_handler(level){	void		  exit();	void		  malloc_dump();	extern int	  malloc_errfd;	if( level & M_HANDLE_DUMP )	{		malloc_dump(malloc_errfd);	}	switch( level & ~M_HANDLE_DUMP )	{		/*		 * If we are to drop a core file and exit		 */		case M_HANDLE_ABORT:			(void) abort();			break;		/*		 * If we are to exit..		 */		case M_HANDLE_EXIT:			exit(200);			break;		/*		 * If we are to dump a core, but keep going on our merry way		 */		case M_HANDLE_CORE:			{				int	  pid;				/*				 * fork so child can abort (and dump core)				 */				if( (pid = fork()) == 0 )				{					(void) write(2,"Child dumping core\n",							(unsigned)9);					(void) abort();				}				/* 				 * wait for child to finish dumping core				 */				while( wait((int *)0) != pid)				{				}				/*				 * Move core file to core.pid.cnt so 				 * multiple cores don't overwrite each				 * other.				 */				if( access("core",0) == 0 )				{					static int	  corecnt;					char	  	  filenam[32];					filenam[0] = 'c';					filenam[1] = 'o';					filenam[2] = 'r';					filenam[3] = 'e';					filenam[4] = '.';					(void)tostring(filenam+5,getpid(),						5, B_DEC, '0');					filenam[10] = '.';					(void)tostring(filenam+11,corecnt++,						3, B_DEC, '0');					filenam[14] = '\0';					(void) unlink(filenam);					if( link("core",filenam) == 0)					{						(void) unlink("core");					}				}			}		/* 		 * If we are to just ignore the error and keep on processing		 */		case M_HANDLE_IGNORE:			break;	} /* switch(... */} /* malloc_err_handler(... *//* * $Log:	malloc.c,v $ * Revision 1.6  90/05/11  00:13:09  cpcahil * added copyright statment *  * Revision 1.5  90/02/25  11:01:18  cpcahil * added support for malloc chain checking. *  * Revision 1.4  90/02/24  21:50:21  cpcahil * lots of lint fixes *  * Revision 1.3  90/02/24  14:51:18  cpcahil * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed *    the function name as a parameter. * 2. Added several function headers. * 3. Changed uses of malloc_fatal/warning to conform to new usage. *  * Revision 1.2  90/02/23  18:05:23  cpcahil * fixed open of error log to use append mode. *  * Revision 1.1  90/02/22  23:17:43  cpcahil * Initial revision *  */

⌨️ 快捷键说明

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