📄 memguard.c
字号:
/*** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)****** This program is free software; you can redistribute it and/or** modify it under the terms of version 2 of the GNU Library General ** Public License as published by the Free Software Foundation.**** This program 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 ** Library General Public License for more details. To obtain a ** copy of the GNU Library General Public License, write to the Free ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.**** Any permitted reproduction of these routines, in whole or in part,** must bear this legend.****** memguard.c**** memory allocation wrapper routines**** NOTE: based on code (c) 1998 the Retrocade group** $Id: memguard.c,v 1.4 2004/02/20 19:53:39 komadori Exp $*/#include "types.h"/* undefine macro definitions, so we get real calls */#undef malloc#undef free#include <string.h>#include <stdlib.h>#if HAVE_INTTYPES_H# include <inttypes.h>#else# if HAVE_STDINT_H# include <stdint.h># endif#endif#include "memguard.h"#include "log.h"/* Maximum number of allocated blocks at any one time */#define MAX_BLOCKS 16384/* Memory block structure */typedef struct memblock_s{ void *block_addr; int block_size; char *file_name; int line_num;} memblock_t;boolean mem_debug = TRUE; /* debugging flag */#ifdef NOFRENDO_DEBUGstatic int mem_blockcount = 0; /* allocated block count */static memblock_t *mem_record = NULL;#define GUARD_STRING "GgUuAaRrDdSsTtRrIiNnGgBbLlOoCcKk"#define GUARD_LENGTH 64 /* before and after allocated block *//*** Check the memory guard to make sure out of bounds writes have not** occurred.*/static boolean mem_checkguardblock(void *data, int guard_size){ uint8 *orig, *chk, *blk; int i, alloc_size; /* get the original pointer */ orig = (((uint8 *) data) - guard_size); /* get the size */ alloc_size = *((uint32 *) orig); /* now skip past the size */ blk = orig + sizeof(uint32); /* check leading guard string */ chk = GUARD_STRING; for (i = sizeof(uint32); i < guard_size; i++) { if (0 == *chk) chk = GUARD_STRING; if (*blk != *chk) return FALSE; chk++; blk++; } /* check end of block */ chk = GUARD_STRING; blk = ((uint8 *) data) + alloc_size; for (i = 0; i < guard_size; i++) { if (0 == *chk) chk = GUARD_STRING; if (*blk != *chk) return FALSE; chk++; blk++; } /* we're okay! */ return TRUE;}/* free a guard block */static void mem_freeguardblock(void *data, int guard_size){ uint8 *orig = (((uint8 *) data) - guard_size); free(orig);}/* fill in the memory guard, advance the pointer to the 'real' memory */static void *mem_guardblock(int alloc_size, int guard_size){ void *orig; uint8 *blk, *chk; int i; /* allocate memory */ orig = calloc(alloc_size + (guard_size * 2), 1); if (NULL == orig) return NULL; blk = ((uint8 *) orig); /* store the size of the newly allocated block*/ *((uint32 *) blk) = alloc_size; /* skip past the size */ blk += sizeof(uint32); /* put guard string at beginning of block */ chk = GUARD_STRING; for (i = sizeof(uint32); i < guard_size; i++) { if (0 == *chk) chk = GUARD_STRING; *blk++ = *chk++; } /* check end of block */ chk = GUARD_STRING; blk = guard_size + (uint8 *) orig + alloc_size; for (i = 0; i < guard_size; i++) { if (0 == *chk) chk = GUARD_STRING; *blk++ = *chk++; } return (void *) (guard_size + (uint8 *) orig);}/* Allocate a bunch of memory to keep track of all memory blocks */static void mem_init(void){ if (mem_record) { free(mem_record); mem_record = NULL; } mem_record = calloc(MAX_BLOCKS * sizeof(memblock_t), 1); ASSERT(mem_record);}/* add a block of memory to the master record */static void mem_addblock(void *data, int block_size, char *file, int line){ int i; for (i = 0; i < MAX_BLOCKS; i++) { if (NULL == mem_record[i].block_addr) { mem_record[i].block_addr = data; mem_record[i].block_size = block_size; mem_record[i].file_name = file; mem_record[i].line_num = line; return; } } ASSERT_MSG("out of memory blocks.");}/* find an entry in the block record and delete it */static void mem_deleteblock(void *data, char *file, int line){ int i; char fail[256]; for (i = 0; i < MAX_BLOCKS; i++) { if (data == mem_record[i].block_addr) { if (FALSE == mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) { sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block corrupt", (uint32) data, line, file); ASSERT_MSG(fail); } memset(&mem_record[i], 0, sizeof(memblock_t)); return; } } sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block not found", (uint32) data, line, file); ASSERT_MSG(fail);}#endif /* NOFRENDO_DEBUG *//* allocates memory and clears it */#ifdef NOFRENDO_DEBUGvoid *_my_malloc(int size, char *file, int line)#elsevoid *_my_malloc(int size)#endif{ void *temp; char fail[256];#ifdef NOFRENDO_DEBUG if (NULL == mem_record && FALSE != mem_debug) mem_init(); if (FALSE != mem_debug) temp = mem_guardblock(size, GUARD_LENGTH); else#endif /* NOFRENDO_DEBUG */ temp = calloc(sizeof(uint8), size); if (NULL == temp) {#ifdef NOFRENDO_DEBUG sprintf(fail, "malloc: out of memory at line %d of %s. block size: %d\n", line, file, size);#else sprintf(fail, "malloc: out of memory. block size: %d\n", size);#endif ASSERT_MSG(fail); }#ifdef NOFRENDO_DEBUG if (FALSE != mem_debug) mem_addblock(temp, size, file, line); mem_blockcount++;#endif return temp;}/* free a pointer allocated with my_malloc */#ifdef NOFRENDO_DEBUGvoid _my_free(void **data, char *file, int line)#elsevoid _my_free(void **data)#endif{ char fail[256]; if (NULL == data || NULL == *data || ((uintptr_t)-1) == (uintptr_t) *data || ((uintptr_t)-1) == (uintptr_t) data) {#ifdef NOFRENDO_DEBUG sprintf(fail, "free: attempted to free NULL pointer at line %d of %s\n", line, file);#else sprintf(fail, "free: attempted to free NULL pointer.\n");#endif ASSERT_MSG(fail); }#ifdef NOFRENDO_DEBUG /* if this is true, we are in REAL trouble */ if (0 == mem_blockcount) { ASSERT_MSG("free: attempted to free memory when no blocks available"); } if (FALSE != mem_debug) mem_deleteblock(*data, file, line); mem_blockcount--; /* dec our block count */ if (FALSE != mem_debug) mem_freeguardblock(*data, GUARD_LENGTH); else#endif /* NOFRENDO_DEBUG */ free(*data); *data = NULL; /* NULL our source */}/* check for orphaned memory handles */void mem_checkleaks(void){#ifdef NOFRENDO_DEBUG int i; if (FALSE == mem_debug) return; if (mem_blockcount) { log_printf("memory leak - %d unfreed block%s\n\n", mem_blockcount, mem_blockcount == 1 ? "" : "s"); for (i = 0; i < MAX_BLOCKS; i++) { if (mem_record[i].block_addr) { log_printf("addr: 0x%08X, size: %d, line %d of %s%s\n", (uint32) mem_record[i].block_addr, mem_record[i].block_size, mem_record[i].line_num, mem_record[i].file_name, (FALSE == mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) ? " -- block corrupt" : ""); } } } else log_printf("no memory leaks\n");#endif}void mem_checkblocks(void){#ifdef NOFRENDO_DEBUG int i; if (FALSE == mem_debug) return; for (i = 0; i < MAX_BLOCKS; i++) { if (mem_record[i].block_addr) { if (FALSE == mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) { log_printf("addr: 0x%08X, size: %d, line %d of %s -- block corrupt\n", (uint32) mem_record[i].block_addr, mem_record[i].block_size, mem_record[i].line_num, mem_record[i].file_name); } } }#endif /* NOFRENDO_DEBUG */}/*** $Log: memguard.c,v $** Revision 1.4 2004/02/20 19:53:39 komadori** Fixed detection of linux framebuffer support. Included xineutils.h in dsputil_mlib.c and added to diff_to_ffmpeg_cvs.txt. Fixed function prototype in dsputil_mlib.c (should be sent back to ffmpeg-dev at some point). Fixed includes in nosefart. Fixed nested comments and includes in goom.**** Revision 1.3 2004/02/19 02:50:25 rockyb** Mandrake patches from** http://cvs.mandrakesoft.com/cgi-bin/cvsweb.cgi/SPECS/xine-lib/** via Goetz Waschk who reports:**** The amd64 patch (xine-lib-1-rc0a-amd64.patch) sets some conservative** CFLAGS for amd64,**** the lib64 patch (xine-lib-1-rc0a-lib64.patch) replaces hardcoded** /lib to support the lib64 library dir on amd64,**** the directfb patch (xine-lib-1-rc2-no-directfb.patch) adds a** configure option to disable directfb,**** the linuxfb patch (xine-lib-1-rc3a-no-linuxfb.patch) does the same** for linux framebuffer and**** the 64bit fixes patch (xine-lib-1-rc3-64bit-fixes.patch) doesn't** apply at the moment against the CVS -- demux_ogg.c was not applied.** it includes some 64 bit pointer and other fixes for 64bit architectures.** from Gwenole Beauchesne**** I haven't tested other than apply and compile.**** Revision 1.2 2003/12/05 15:55:01 f1rmb** cleanup phase II. use xprintf when it's relevant, use xine_xmalloc when it's relevant too. Small other little fix (can't remember). Change few internal function prototype because it xine_t pointer need to be used if some xine's internal sections. NOTE: libdvd{nav,read} is still too noisy, i will take a look to made it quit, without invasive changes. To be continued...**** Revision 1.1 2003/01/08 07:04:35 tmmm** initial import of Nosefart sources**** Revision 1.8 2000/06/26 04:54:48 matt** simplified and made more robust**** Revision 1.7 2000/06/12 01:11:41 matt** cleaned up some error output for win32**** Revision 1.6 2000/06/09 15:12:25 matt** initial revision***/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -