www.pudn.com > gandalf.1.zip > misc_defs.c
/** * File: $RCSfile: misc_defs.c,v $ * Module: Miscellaneous definitions * Part of: Gandalf Library * * Revision: $Revision: 1.20 $ * Last edited: $Date: 2006/03/17 14:34:10 $ * Author: $Author: pm $ * Copyright: (c) 2000 Imagineer Software Limited */ /* 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 GAN_DONT_DEFINE_MALLOC #include#include #include #include /** * \mainpage Gandalf: The Fast Computer Vision and Numerical Library */ /** * \addtogroup Common * \{ */ /** * \defgroup CommonMisc Miscellaneous Definitions and Functions * \{ */ #ifndef NDEBUG /** *\brief debug flag; can be set interactively in debugger to switch on various messages */ GANDALF_API Gan_Bool gan_debug = GAN_FALSE; #endif /** * \brief Array of sizes of simple types used in Gandalf. */ const size_t gan_type_sizes[] = { sizeof(char), /**< corresponding to label #GAN_CHAR */ sizeof(unsigned char), /**< corresponding to label #GAN_UCHAR */ sizeof(short), /**< corresponding to label #GAN_SHORT */ sizeof(unsigned short), /**< corresponding to label #GAN_USHORT */ sizeof(int), /**< corresponding to label #GAN_INT */ sizeof(unsigned int), /**< corresponding to label #GAN_UINT */ sizeof(long), /**< corresponding to label #GAN_LONG */ sizeof(unsigned long), /**< corresponding to label #GAN_ULONG */ #if (SIZEOF_LONG_LONG != 0) sizeof(long long), /**< corresponding to label #GAN_LONGLONG */ #endif sizeof(float), /**< corresponding to label #GAN_FLOAT */ sizeof(double), /**< corresponding to label #GAN_DOUBLE */ sizeof(long double), /**< corresponding to label #GAN_LONGDOUBLE */ sizeof(char *), /**< corresponding to label #GAN_STRING */ sizeof(Gan_Bool), /**< corresponding to label #GAN_BOOL */ sizeof(void *) /**< corresponding to label #GAN_POINTER */ }; /** * \brief Generates a string identifier for an internal type. * \param format Image format, e.g. #GAN_UINT8 * \return String identifier, e.g. "8-bit", or "" for unknown format. */ const char *gan_type_string ( Gan_Type type ) { switch(type) { case GAN_INT8: return "signed 8-bit"; break; case GAN_UINT8: return "8-bit"; break; case GAN_INT16: return "signed 16-bit"; break; case GAN_UINT16: return "16-bit"; break; case GAN_INT32: return "signed 32-bit"; break; case GAN_UINT32: return "32-bit"; break; #ifdef GAN_UINT64 case GAN_INT64: return "signed 64-bit"; break; case GAN_UINT64: return "64-bit"; break; #endif case GAN_FLOAT32: return "32-bit float"; break; case GAN_FLOAT64: return "64-bit float"; break; case GAN_BOOL: return "Boolean"; break; case GAN_POINTER: return "Pointer"; break; default: break; } /* unknown type */ gan_err_flush_trace(); gan_err_register ( "gan_type_string", GAN_ERROR_ILLEGAL_TYPE, "" ); return ""; } #ifdef GAN_MALLOC_DEBUG #include typedef enum { GAN_MALLOC, GAN_CALLOC, GAN_DOUBLELOC } Gan_MallocType; typedef struct Gan_MallocStackStruct { int line; char *file; struct Gan_MallocStackStruct *next; } Gan_MallocStackStruct; typedef struct Gan_MallocStruct { unsigned line; char *file; Gan_MallocType type; void *ptr; size_t size, bsize; Gan_MallocStackStruct *stack; struct Gan_MallocStruct *next; } Gan_MallocStruct; static Gan_MallocStackStruct *stack = NULL; static Gan_MallocStruct *list = NULL; static void stack_element_free ( Gan_MallocStackStruct *stack ) { free ( stack->file ); free ( stack ); } static void stack_free ( Gan_MallocStackStruct *stack ) { if ( stack == NULL ) return; stack_free ( stack->next ); stack_element_free ( stack ); } static Gan_MallocStackStruct * copy_reversed_stack ( Gan_MallocStackStruct *stack ) { Gan_MallocStackStruct *stack_copy = NULL; for ( ; stack != NULL; stack = stack->next ) { Gan_MallocStackStruct *new = (Gan_MallocStackStruct *) malloc(sizeof(Gan_MallocStackStruct)); assert ( new != NULL ); new->line = stack->line; new->file = (char *) malloc((strlen(stack->file)+1)*sizeof(char)); assert ( new->file != NULL ); strcpy ( new->file, stack->file ); new->next = stack_copy; stack_copy = new; } return stack_copy; } static void add_to_malloc_list ( unsigned line, const char *file, Gan_MallocType type, void *ptr, size_t size, size_t bsize ) { Gan_MallocStruct *new = (Gan_MallocStruct *) malloc(sizeof(Gan_MallocStruct)); assert ( new != NULL ); /* fill fields of new structure */ new->line = line; new->file = (char *) malloc((strlen(file)+1)*sizeof(char)); assert ( new->file != NULL ); strcpy ( new->file, file ); new->type = type; new->ptr = ptr; new->size = size*bsize; new->bsize = bsize; new->stack = copy_reversed_stack(stack); /* insert new block in list */ new->next = list; list = new; } static void remove_from_malloc_list ( void *ptr ) { Gan_MallocStruct *lptr, *prev; /* search through list for given pointer */ for ( prev = NULL, lptr = list; lptr != NULL; prev = lptr, lptr = lptr->next ) if ( lptr->ptr == ptr ) { if ( prev == NULL ) list = lptr->next; else prev->next = lptr->next; stack_free(lptr->stack); free(lptr->file); free(lptr); break; } assert ( lptr != NULL ); } /** * \brief Gandalf debugging version of \c calloc(). * \param file The file in which \c calloc() was called * \param line The line number that \c calloc() was called from * \param nmemb The number of blocks of data to allocate * \param size The size of each block * \return Pointer allocated from the heap, or \c NULL on failure. * * Puts details of the \c calloc() call into a linked list for subsequent * analysis of the heap. * * This function is for debug purposes only and is not thread-safe. */ void * gan_calloc ( const char *file, unsigned line, size_t nmemb, size_t size ) { void *ptr = calloc(nmemb, size); add_to_malloc_list ( line, file, GAN_CALLOC, ptr, nmemb, size ); return ptr; } /** * \brief Gandalf debugging version of \c malloc(). * \param file The file in which \c malloc() was called * \param line The line number that \c malloc() was called from * \param size The size of the block of memory to be allocated * \return Pointer allocated from the heap, or \c NULL on failure. * * Puts details of the \c malloc() call into a linked list for subsequent * analysis of the heap. * * This function is for debug purposes only and is not thread-safe. */ void * gan_malloc ( const char *file, unsigned line, size_t size ) { void *ptr = malloc(size); add_to_malloc_list ( line, file, GAN_MALLOC, ptr, size, 1 ); return ptr; } /** * \brief Gandalf debugging version of \c realloc(). * \param file The file in which realloc() was called * \param line The line number that realloc() was called from * \param ptr A previously allocated memory block or NULL * \param size The size of the block of memory to be allocated * \return Pointer allocated from the heap, or \c NULL on failure. * * Puts details of the \c malloc() call into a linked list for subsequent * analysis of the heap. * * This function is for debug purposes only and is not thread-safe. */ void * gan_realloc ( const char *file, unsigned line, void *ptr, size_t size ) { if ( ptr != NULL ) remove_from_malloc_list ( ptr ); ptr = realloc(ptr,size); add_to_malloc_list ( line, file, GAN_DOUBLELOC, ptr, size, 1 ); return ptr; } /** * \brief Gandalf debugging version of \c free(). * \param ptr A previously allocated memory block * \return No value. * * Removes details of a previous \c malloc(), \c calloc() or \c realloc() call * from a linked list. * * This function is for debug purposes only and is not thread-safe. */ void gan_free ( void *ptr ) { remove_from_malloc_list ( ptr ); free ( ptr ); } /** * \brief Prints a report on the current heap status to \c stderr. * \param file A file to which to print the report or \c NULL * \return No value. * * Prints a report on the current heap status to the given \a file, or to * \c stderr if \a file is passed as \c NULL. */ Gan_Bool gan_heap_report(const char *file) { Gan_MallocStruct *lptr; FILE *fp; if ( file == NULL ) fp = stderr; else { fp = fopen ( file, "w" ); if ( fp == NULL ) { gan_err_flush_trace(); gan_err_register ( "gan_heap_report", GAN_ERROR_OPENING_FILE, "" ); return GAN_FALSE; } } for ( lptr = list; lptr != NULL; lptr = lptr->next ) { Gan_MallocStackStruct *ptr; switch ( lptr->type ) { case GAN_MALLOC: fprintf ( fp, "malloc of %d bytes (%p) at line %d of file %s\n", lptr->size, lptr->ptr, lptr->line, lptr->file ); break; case GAN_CALLOC: fprintf ( fp, "calloc of %d bytes (%p) at line %d of file %s (block size %d)\n", lptr->size, lptr->ptr, lptr->line, lptr->file, lptr->bsize ); break; case GAN_DOUBLELOC: fprintf ( fp, "realloc of %d bytes (%p) at line %d of file %s\n", lptr->size, lptr->ptr, lptr->line, lptr->file ); break; default: assert(0); break; } for ( ptr = lptr->stack; ptr != NULL; ptr = ptr->next ) fprintf ( fp, " called from line %d of file %s\n", ptr->line, ptr->file ); } /* success */ if ( file != NULL ) fclose(fp); return GAN_TRUE; } void gan_heap_push_fileline ( const char *file, int line ) { Gan_MallocStackStruct *new = (Gan_MallocStackStruct *) malloc(sizeof(Gan_MallocStackStruct)); assert ( new != NULL ); new->file = (char *) malloc(strlen(file)+1); new->line = line; assert ( new->file != NULL ); strcpy ( new->file, file ); new->next = stack; stack = new; } void gan_heap_pop(void) { Gan_MallocStackStruct *next; assert ( stack != NULL ); next = stack->next; stack_element_free ( stack ); stack = next; } #endif /* #ifdef GAN_MALLOC_DEBUG */ /* define memcpy if it is not part of the C library */ #ifndef HAVE_MEMCPY void * memcpy ( void *dest, const void *src, size_t n ) { char *chdest = (char *)dest, *chsrc = (char *)src; int intn; for ( intn = (int)n-1; intn >= 0; intn-- ) *chdest++ = *chsrc++; return dest; } #endif /* #ifndef HAVE_MEMCPY */ /** * \} */ /** * \} */