"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "odt2txt-0.4/mem.c" of archive odt2txt-0.4.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  * mem.c: memory allocation wrappers with a few simple checks
    3  *
    4  * Copyright (c) 2002-2008 Dennis Stosberg <dennis@stosberg.net>
    5  *
    6  * This program is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU General Public License,
    8  * version 2 as published by the Free Software Foundation
    9  */
   10 
   11 #include "mem.h"
   12 
   13 #ifdef MEMDEBUG
   14 static void    meminfo_add(void *p, size_t size, const char *file, int line);
   15 static void    meminfo_rm(void *p, const char *file, int line);
   16 static MEMINFO *meminfo_getinfo(void *p);
   17 static void    print_memory_stats(void);
   18 static void    die(const char *format, ...);
   19 static void    warn(const char *format, ...);
   20 
   21 static size_t  mem_num_malloced    = 0;
   22 static size_t  mem_bytes_malloced  = 0;
   23 
   24 static size_t  mem_num_freed       = 0;
   25 static size_t  mem_bytes_freed     = 0;
   26 
   27 static MEMINFO **meminfo = NULL;
   28 static size_t  meminfo_size  = 0;
   29 static size_t  meminfo_count = 0;
   30 
   31 static unsigned char magic[] = { 0xFE, 0xDC, 0xBA, 0x98,
   32 				 0x76, 0x54, 0x32, 0x10 };
   33 
   34 /**
   35  *  Adds information about an newly allocated memory region to the
   36  *  meminfo structure.
   37  */
   38 static void meminfo_add(void *p, size_t size, const char *file, int line) {
   39 
   40 	if(!meminfo)
   41 		if(atexit(print_memory_stats))
   42 			warn("Memory statistics will not be shown.");
   43 
   44 	/* enlarge MEMINFO structure if necessary */
   45 	if(meminfo_count == meminfo_size) {
   46 		meminfo_size = meminfo_size ? meminfo_size << 1 : 1;
   47 		meminfo = realloc(meminfo, meminfo_size * sizeof(MEMINFO*));
   48 	}
   49 
   50 	/* add information to structure */
   51 	meminfo[meminfo_count] = malloc(sizeof(MEMINFO));
   52 	meminfo[meminfo_count]->addr = p;
   53 	meminfo[meminfo_count]->size = size;
   54 	meminfo[meminfo_count]->file = file;
   55 	meminfo[meminfo_count]->line = line;
   56 	meminfo_count++;
   57 #ifdef MEMINFO_VERBOSE
   58 	printf("allocated 0x%x at %s:%d\n", p, file, line);
   59 #endif
   60 	mem_bytes_malloced += size;
   61 	mem_num_malloced++;
   62 }
   63 
   64 
   65 /**
   66  *  Removes information about a just freed memory region to the
   67  *  meminfo structure.  Halts the program if the region to be freed
   68  *  has never been allocated at all.
   69  */
   70 static void meminfo_rm(void *p, const char *file, int line) {
   71 	size_t i;
   72 
   73 	for(i = 0; i < meminfo_count; ++i) {
   74 		if(p == meminfo[i]->addr) {
   75 #ifdef MEMINFO_VERBOSE
   76 			fprintf(stderr, "freed 0x%x at %s:%d\n",
   77 				p, file, line);
   78 			fprintf(stderr, "  was allocated at %s:%d\n",
   79 				meminfo[i]->file, meminfo[i]->line);
   80 #endif
   81 			mem_bytes_freed += meminfo[i]->size;
   82 			free(meminfo[i]);
   83 			meminfo[i] = meminfo[meminfo_count - 1];
   84 			meminfo_count--;
   85 			mem_num_freed++;
   86 			return;
   87 		}
   88 	}
   89 
   90 	die("Tried to free a piece of memory at 0x%p in %s:%d"
   91 	    " which is not allocated", (void*)p, file, line);
   92 }
   93 
   94 
   95 /**
   96  *  Returns the size of a malloc'ed region.
   97  */
   98 static MEMINFO *meminfo_getinfo(void *p) {
   99 	size_t i;
  100 
  101 	for(i = 0; i < meminfo_count; ++i)
  102 		if(p == meminfo[i]->addr)
  103 			return(meminfo[i]);
  104 	return(0);
  105 }
  106 
  107 
  108 /**
  109  *  Prints statistics about allocated and deallocated memory to
  110  *  stderr just before the program exits.  If there are memory
  111  *  regions left that were allocated but never freed, it will print
  112  *  information on those regions as well.
  113  */
  114 static void print_memory_stats(void) {
  115 	size_t i;
  116 
  117 	if(mem_num_malloced == mem_num_malloced
  118 	   && mem_bytes_malloced == mem_bytes_freed)
  119 		return;
  120 
  121 	fprintf(stderr, "Memory statistics: \n"
  122 		"  %lu allocations   (%lu bytes)\n"
  123 		"  %lu deallocations (%lu bytes)\n"
  124 		"  %ld difference    (%ld bytes)\n",
  125 		(unsigned long)mem_num_malloced,
  126 		(unsigned long)mem_bytes_malloced,
  127 		(unsigned long)mem_num_freed,
  128 		(unsigned long)mem_bytes_freed,
  129 		(long)(mem_num_malloced - mem_num_freed),
  130 		(long)(mem_bytes_malloced - mem_bytes_freed)
  131 		);
  132 
  133 	if(meminfo_count) {
  134 		fprintf(stderr, "%lu malloc'ed regions were never "
  135 			"free'd:\n", (unsigned long)meminfo_count);
  136 		for(i = 0; i < meminfo_count; ++i) {
  137 			fprintf(stderr, "  %p (%lu bytes) allocated at %s:%d\n",
  138 				(void *)meminfo[i]->addr,
  139 				(unsigned long)meminfo[i]->size,
  140 				meminfo[i]->file, meminfo[i]->line);
  141 			free(meminfo[i]);
  142 		}
  143 		free(meminfo);
  144 	}
  145 }
  146 
  147 
  148 /**
  149  *  Allocates memory and records information on the allocated
  150  *  memory.  It will halt the program if the memory region to be
  151  *  allocated has a size of zero.
  152  */
  153 void *ymalloc_dbg(size_t size, const char *file, int line) {
  154 	void *p;
  155 
  156 	if(!size)
  157 		die("Trying to allocate 0 bytes at %s:%d", file, line);
  158 
  159 	p = malloc(size + 2*sizeof(magic));
  160 	if(!p)
  161 		die("Out of memory at %s:%d while trying to allocate %lu bytes",
  162 		    file, line, (unsigned long)size);
  163 
  164 	meminfo_add(p, size, file, line);
  165 
  166 	memcpy(p, &magic, sizeof(magic));
  167 	memcpy((char*)p + size + sizeof(magic), &magic, sizeof(magic));
  168 
  169 	return((char*)p + sizeof(magic));
  170 }
  171 
  172 
  173 /**
  174  *  Frees memory and removes information on the memory region. Halts
  175  *  the program, if the region to be freed has never been allocated
  176  *  at all.
  177  */
  178 void yfree_dbg(void *p, const char *file, int line) {
  179 	MEMINFO *info;
  180 
  181 	if(!p)
  182 		die("Trying to free null pointer at %s:%d", file, line);
  183 
  184 	info = meminfo_getinfo((char*)p - sizeof(magic));
  185 
  186 	if(info == NULL) {
  187 		die("Looks like we were asked to free a piece of memory"
  188 		    " that we never allocated: %s:%d", file, line);
  189 	}
  190 
  191 	/* Check, if region boundaries are intact. */
  192 	if(memcmp((char*)p - sizeof(magic), &magic, sizeof(magic))
  193 	   || memcmp((char*)p + info->size, &magic, sizeof(magic))) {
  194 		die("The boundaries of a region allocated at %s:%d were "
  195 		    "overwritten.", info->file, info->line);
  196 	}
  197 
  198 	free((char*)p - sizeof(magic));
  199 	meminfo_rm((char*)p - sizeof(magic), file, line);
  200 
  201 	p = NULL;
  202 }
  203 
  204 
  205 /**
  206  *  Allocates memory and records information on the allocated
  207  *  memory.  This function will halt the program if the memory
  208  *  region to be allocated has a size of zero.
  209  */
  210 void *ycalloc_dbg(size_t number, size_t size, const char *file, int line) {
  211 	void *p;
  212 	p = ymalloc_dbg(number * size, file, line);
  213 	memset(p, 0, number * size);
  214 	return(p);
  215 }
  216 
  217 
  218 /**
  219  *  Reallocates memory and updates the information on the memory
  220  *  region.  This function will halt the program if new size of the
  221  *  memory region is zero ot the region has never been allocated
  222  *  with ymalloc or ycalloc.
  223  */
  224 void *yrealloc_dbg(void *p, size_t size, const char *file, int line) {
  225 	MEMINFO *area_info;
  226 
  227 	if(!size) {
  228 		die("Trying to reallocate 0 bytes at %s:%d", file, line);
  229 	}
  230 
  231 	if(!p) {
  232 		p = ymalloc_dbg(size, file, line);
  233 		return(p);
  234 	}
  235 
  236 	/* Check, if region boundaries are intact. */
  237 	area_info = meminfo_getinfo((char*)p - sizeof(magic));
  238 	if(memcmp((char*)p - sizeof(magic), &magic, sizeof(magic)) ||
  239 	   memcmp((char*)p + area_info->size, &magic, sizeof(magic))) {
  240 		die("The boundaries of a region allocated at %s:%d were "
  241 		    "overwritten.", area_info->file, area_info->line);
  242 	}
  243 
  244 	meminfo_rm((char*)p - sizeof(magic), file, line);
  245 	p = realloc((char*)p - sizeof(magic), size + 2*sizeof(magic));
  246 
  247 	if(!p)
  248 		die("Out of memory at %s:%d while trying to allocate %lu bytes",
  249 		    file, line, (unsigned long)size);
  250 
  251 	/* realloc has copied the magic at the beginning of the
  252 	   memory area.  We need to set the final magic only    */
  253 	memcpy((char*)p + size + sizeof(magic), &magic, sizeof(magic));
  254 	meminfo_add(p, size, file, line);
  255 
  256 	return((char*)p + sizeof(magic));
  257 }
  258 
  259 
  260 /**
  261  *  Prints an error message to stdout and halts the program
  262  */
  263 static void warn(const char *format, ...) {
  264 	va_list argp;
  265 	va_start(argp, format);
  266 	vfprintf(stderr, format, argp);
  267 	va_end(argp);
  268 	fprintf(stderr, "\n");
  269 }
  270 
  271 /**
  272  *  Prints an error message to stdout and halts the program
  273  */
  274 static void die(const char *format, ...) {
  275 	va_list argp;
  276 	va_start(argp, format);
  277 	vfprintf(stderr, format, argp);
  278 	va_end(argp);
  279 	fprintf(stderr, "\n");
  280 	exit(EXIT_FAILURE);
  281 }
  282 
  283 #endif