IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 648


Ignore:
Timestamp:
May 12, 2004, 9:05:02 AM (22 years ago)
Author:
desonia
Message:

Added buffer overflow detection and doxygen comments.

Location:
trunk/psLib/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/Doxyfile

    r515 r648  
    1515#---------------------------------------------------------------------------
    1616
    17 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
     17# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
    1818# by quotes) that should identify the project.
    1919
     
    833833
    834834#---------------------------------------------------------------------------
    835 # Configuration options related to the preprocessor   
    836 #---------------------------------------------------------------------------
    837 
    838 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
    839 # evaluate all C-preprocessor directives found in the sources and include 
     835# Configuration options related to the preprocessor
     836#---------------------------------------------------------------------------
     837
     838# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
     839# evaluate all C-preprocessor directives found in the sources and include
    840840# files.
    841841
     
    874874
    875875# The PREDEFINED tag can be used to specify one or more macro names that
    876 # are defined before the preprocessor is started (similar to the -D option of 
    877 # gcc). The argument of the tag is a list of macros of the form: name 
    878 # or name=definition (no spaces). If the definition and the = are 
     876# are defined before the preprocessor is started (similar to the -D option of
     877# gcc). The argument of the tag is a list of macros of the form: name
     878# or name=definition (no spaces). If the definition and the = are
    879879# omitted =1 is assumed.
    880880
    881 PREDEFINED             =
    882 
    883 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
    884 # this tag can be used to specify a list of macro names that should be expanded. 
     881PREDEFINED             = DOXYGEN
     882
     883# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
     884# this tag can be used to specify a list of macro names that should be expanded.
    885885# The macro definition that is found in the sources will be used.
    886886# Use the PREDEFINED tag if you want to use a different macro definition.
  • trunk/psLib/src/sys/psMemory.c

    r639 r648  
    88 *  @author Robert Lupton, Princeton University
    99 *
    10  *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2004-05-11 20:11:17 $
     10 *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
     11 *  @date $Date: 2004-05-12 19:05:02 $
    1212 *
    1313 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2020#include <stdio.h>
    2121#include <stdbool.h>
     22#include <stdint.h>
    2223
    2324#include "psMemory.h"
     
    3435 * Unique ID for allocated blocks
    3536 */
    36 static unsigned long memid = 0;
     37static psMemoryId memid = 0;
    3738
    3839/**
     
    6263                                      const char *file, int lineno)
    6364{
    64     if (ptr->refCounter <= 0) {
     65    if (ptr->refCounter < 1) {
    6566        psError(__func__,
    6667                "Block %ld allocated at %s:%d freed more than once at %s:%d\n",
     
    9596 * Call the callbacks when these IDs are allocated/freed
    9697 */
    97 long p_psMemAllocateID = 0;  // notify user this block is allocated
    98 long p_psMemFreeID = 0;   // notify user this block is freed
    99 
    100 long psMemAllocateCallbackSetID(long id) // set p_psMemAllocateID to id
    101 {
    102     long old = p_psMemAllocateID;
     98psMemoryId p_psMemAllocateID = 0;  // notify user this block is allocated
     99psMemoryId p_psMemFreeID = 0;   // notify user this block is freed
     100
     101psMemoryId psMemAllocateCallbackSetID(psMemoryId id) // set p_psMemAllocateID to id
     102{
     103    psMemoryId old = p_psMemAllocateID;
    103104    p_psMemAllocateID = id;
    104105
     
    106107}
    107108
    108 long psMemFreeCallbackSetID(long id)  // set p_psMemFreeID to id
    109 {
    110     long old = p_psMemFreeID;
     109psMemoryId psMemFreeCallbackSetID(psMemoryId id)  // set p_psMemFreeID to id
     110{
     111    psMemoryId old = p_psMemFreeID;
    111112    p_psMemFreeID = id;
    112113
     
    120121 * isn't resignalled)
    121122 */
    122 static long memAllocateCallbackDefault(const psMemBlock *ptr)
    123 {
    124     static int incr = 0;  // "p_psMemAllocateID += incr"
     123static psMemoryId memAllocateCallbackDefault(const psMemBlock *ptr)
     124{
     125    static psMemoryId incr = 0;  // "p_psMemAllocateID += incr"
    125126
    126127    return incr;
    127128}
    128129
    129 static long memFreeCallbackDefault(const psMemBlock *ptr)
    130 {
    131     static int incr = 0;  // "p_psMemFreeID += incr"
     130static psMemoryId memFreeCallbackDefault(const psMemBlock *ptr)
     131{
     132    static psMemoryId incr = 0;  // "p_psMemFreeID += incr"
    132133
    133134    return incr;
     
    169170 * Return memory ID counter for next block to be allocated
    170171 */
    171 int psMemGetId(void)
     172psMemoryId psMemGetId(void)
    172173{
    173174    return memid + 1;
     
    199200
    200201    if (m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {
    201         psError(funcName, "psMemCheckCorruption: memory block %ld is corrupted (%p %p)",
     202        psError(funcName, "psMemCheckCorruption: memory block %ld is corrupted (buffer underflow %p %p)",
    202203                m->id,m->startblock,m->endblock);
     204        return(1);
     205    }
     206    if (*(void**)((int8_t*)(m+1)+m->userMemorySize) != P_PS_MEMMAGIC) {
     207        psError(funcName, "psMemCheckCorruption: memory block %ld is corrupted (buffer overflow, %p)",
     208                m->id,*(void**)((int8_t*)(m+1)+m->userMemorySize));
    203209        return(1);
    204210    }
     
    236242void *p_psAlloc(size_t size, const char *file, int lineno)
    237243{
    238     psMemBlock *ptr = malloc(sizeof(psMemBlock) + size);
     244    psMemBlock *ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));
    239245
    240246    if (ptr == NULL) {
     
    246252    }
    247253
    248     *(unsigned long*)&ptr->id = ++memid;
     254    *(psMemoryId*)&ptr->id = ++memid;
    249255    ptr->file = file;
    250256    *(unsigned int*)&ptr->lineno = lineno;
     
    252258    ptr->endblock = P_PS_MEMMAGIC;
    253259    ptr->refCounter = 1;                // one user so far
     260    ptr->userMemorySize = size;
     261    *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;
    254262
    255263    // need exclusive access of the memory block list now...
     
    287295        isBlockLast = (ptr == lastMemBlockAllocated);
    288296
    289         ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size);
     297        ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size + sizeof(void*));
    290298
    291299        if (ptr == NULL) {
     
    293301                    size, file, lineno);
    294302        }
     303
     304        ptr->userMemorySize = size;
     305        *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;
    295306
    296307        if (isBlockLast) {
     
    363374 */
    364375int psMemCheckLeaks(
    365     int id0,                            // don't list blocks with id < id0
     376    psMemoryId id0,                     // don't list blocks with id < id0
    366377    psMemBlock ***arr,                  // pointer to array of pointers to leaked blocks, or NULL
    367378    FILE *fd)                           // print list of leaks to fd (or NULL)
     
    416427 * Reference counting APIs
    417428 */
    418 int psMemGetRefCounter(void *vptr) // return refCounter
     429psReferenceCount psMemGetRefCounter(void *vptr) // return refCounter
    419430{
    420431    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
  • trunk/psLib/src/sys/psMemory.h

    r639 r648  
    1212 *  @author Robert Lupton, Princeton University
    1313 *
    14  *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
    15  *  @date $Date: 2004-05-11 20:11:17 $
     14 *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
     15 *  @date $Date: 2004-05-12 19:05:02 $
     16 *
     17 *  @ingroup SystemGroup System Utilities
    1618 *
    1719 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1921
    2022#include <stdio.h>                      // needed for FILE
     23
     24
     25/** @addtogroup MemoryManagement Memory Management Utilities
     26 *  @ingroup SystemGroup
     27 *
     28 *  This is the generic memory management system put inbetween the user's high level code and the OS-level
     29 *  memory allocation routines.  This system adds such features as callback routines for memory error events,
     30 *  tracing capabilities, and reference counting.
     31 *  @{
     32 */
     33
     34/**
     35 *  @addtogroup memCallback Memory Callbacks
     36 *
     37 *  Routines dealing with the creating and setting of memory management callback functions.
     38 */
     39
     40/**
     41 *  @addtogroup memRefCount Reference Count
     42 *
     43 *  Routines dealing with the reference counting of allocated buffers.
     44 */
     45
     46/// typedef for memory identification numbers.  Guaranteed to be some variety of integer.
     47typedef unsigned long psMemoryId;
     48
     49/// typedef for a memory block's reference count. Guaranteed to be some variety of integer.
     50typedef unsigned long psReferenceCount;
    2151
    2252/** Book-keeping data for storage allocator.
     
    3060    struct psMemBlock* previousBlock;   ///< previous block in allocation list
    3161    struct psMemBlock* nextBlock;       ///< next block allocation list
    32     const unsigned long id;             ///< a unique ID for this allocation
     62    size_t  userMemorySize;             ///< the size of the user-portion of the memory block
     63    const psMemoryId id;                ///< a unique ID for this allocation
    3364    const char* file;                   ///< set from __FILE__ in e.g. p_psAlloc
    3465    const int lineno;                   ///< set from __LINE__ in e.g. p_psAlloc
    35     unsigned int refCounter;            ///< how many times pointer is referenced
     66    psReferenceCount refCounter;            ///< how many times pointer is referenced
    3667    const void* endblock;               ///< initialised to p_psMEMMAGIC
    3768}
    3869psMemBlock;
    3970
    40 /// prototype of a basic callback used by memory functions
    41 typedef long (*psMemAllocateCallback)(const psMemBlock *ptr);
    42 
    43 /// prototype of memory free callback used by memory functions
    44 typedef long (*psMemFreeCallback)(const psMemBlock *ptr);
     71/** prototype of a basic callback used by memory functions
     72 *
     73 *  @see psMemAllocateCallbackSet
     74 *  @ingroup memCallback
     75 */
     76typedef psMemoryId (*psMemAllocateCallback)(
     77    const psMemBlock *ptr           ///< the psMemBlock just allocated
     78);
     79
     80/** prototype of memory free callback used by memory functions
     81 *
     82 *  @see psMemFreeCallbackSet
     83 *  @ingroup memCallback
     84 */
     85typedef psMemoryId (*psMemFreeCallback)(
     86    const psMemBlock *ptr           ///< the psMemBlock being freed
     87);
    4588
    4689/** prototype of a callback used in error conditions
    4790 *
    48  *  This callback should never try to call psAlloc or psFree.
    49  *
    50  */
    51 typedef void (*psMemProblemCallback)(const psMemBlock *ptr, const char *file, int lineno);
    52 
    53 /// prototype of a callback used when memory runs out
    54 typedef void *(*psMemExhaustedCallback)(size_t size);
    55 
    56 /** Private Functions **************************************************************/
    57 /** \addtogroup sysUtils memory private
    58  *  \{
    59  */
    60 
    61 /// Memory allocation. Underlying private function called by macro psAlloc.
    62 void* p_psAlloc(size_t size,  ///< Size required
    63                 const char *file, ///< File of call
    64                 int lineno)  ///< Line number of call
    65 ;
    66 
    67 /// Memory re-allocation.  Underlying private function called by macro psRealloc.
    68 void* p_psRealloc(void *ptr,  ///< Pointer to re-allocate
    69                   size_t size,  ///< Size required
    70                   const char *file, ///< File of call
    71                   int lineno)  ///< Line number of call
    72 ;
    73 
    74 /// Free memory.  Underlying private function called by macro psFree.
    75 void p_psFree(void *ptr,  ///< Pointer to free
    76               const char *file,  ///< File of call
    77               int lineno)  ///< Line number of call
    78 ;
    79 /** Public Functions **************************************************************/
    80 /** \}
    81  *  \addtogroup sysUtils memory psLibAPI
    82  *  \{
    83  */
    84 
    85 /// Check for memory leaks
     91 *  This callback should not try to call psAlloc or psFree.
     92 *
     93 *  @see psMemProblemCallbackSet
     94 *  @ingroup memCallback
     95 */
     96typedef void (*psMemProblemCallback)(
     97    const psMemBlock *ptr,          ///< the pointer to the problematic memory block.
     98    const char *file,               ///< the file in which the problem originated
     99    int lineno                      ///< the line number in which the problem originated
     100);
     101
     102/** prototype of a callback function used when memory runs out
     103 *
     104 *  @return void* pointer to requested buffer of the size size_t, or NULL if memory could not
     105 *          be found.
     106 *
     107 *  @see psMemExhaustedCallbackSet
     108 *  @ingroup memCallback
     109 */
     110typedef void *(*psMemExhaustedCallback)(
     111    size_t size                     //< the size of buffer required
     112);
     113
     114/** Memory allocation.  This operates much like malloc(), but is guaranteed to return a non-NULL value.
     115 *
     116 *  @return void* pointer to the allocated buffer. This will not be NULL.
     117 *  @see psFree
     118 */
     119#ifdef DOXYGEN
     120void* psAlloc(
     121    size_t size                     ///< Size required
     122);
     123#else
     124void* p_psAlloc(
     125    size_t size,                    ///< Size required
     126    const char *file,               ///< File of call
     127    int lineno                      ///< Line number of call
     128);
     129/// Memory allocation. psAlloc sends file and line number to p_psAlloc.
     130#define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
     131#endif
     132
     133
     134/** Memory re-allocation.  This operates much like realloc(), but is guaranteed to return a non-NULL value.
     135 *
     136 *  @return void* pointer to resized buffer. This will not be NULL.
     137 *  @see psAlloc, psFree
     138 */
     139#ifdef DOXYGEN
     140void* psRealloc(void *ptr               ///< Pointer to re-allocate
     141               );
     142#else
     143void* p_psRealloc(void *ptr,            ///< Pointer to re-allocate
     144                  size_t size,          ///< Size required
     145                  const char *file,     ///< File of call
     146                  int lineno            ///< Line number of call
     147                 );
     148
     149/// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
     150#define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
     151
     152#endif
     153
     154
     155/** Free memory.  This operates much like free().
     156 *
     157 *  @see psAlloc, psRealloc
     158 */
     159#ifdef DOXYGEN
     160void psFree(void *ptr,                  ///< Pointer to free, if NULL, function returns immediately.
     161           );
     162#else
     163void p_psFree(void *ptr,                ///< Pointer to free
     164              const char *file,         ///< File of call
     165              int lineno                ///< Line number of call
     166             );
     167
     168/// Free memory.  psFree sends file and line number to p_psFree.
     169#define psFree(size) p_psFree(size, __FILE__, __LINE__)
     170
     171#endif
     172
     173/** Check for memory leaks.  This scans for allocated memory buffers not freed with an ID not less than id0.
     174 *  This is used to check for memory leaks by:
     175 *      -# before a block of code to be checked, store the current ID count via psGetMemId
     176 *      -# after the block of code to be checked, call this function using the ID stored above.  If all
     177 *         memory in the block that was allocated has been freed, this call should output nothing and
     178 *         return 0.
     179 *
     180 *  If memory leaks are found, the Memory Problem callback will be called as well.
     181 *
     182 *  return int  number of memory blocks found as 'leaks', i.e., the number of currently allocated memory
     183 *              blocks above id0 that have not been freed.
     184 *  @see psAlloc, psFree, psgetMemId, psMemProblemCallbackSet
     185 */
    86186int psMemCheckLeaks(
    87     int id0,                        ///< don't list blocks with id < id0
     187    psMemoryId id0,              ///< don't list blocks with id < id0
    88188    psMemBlock ***arr,              ///< pointer to array of pointers to leaked blocks, or NULL
    89189    FILE *fd                        ///< print list of leaks to fd (or NULL)
    90190);
    91191
    92 /// Check for memory corruption
     192/** Check for memory corruption.  Scans all currently allocated memory buffers and checks for corruptions,
     193 *  i.e., invalid markers that signify a buffer under/overflow.
     194 *
     195 */
    93196int psMemCheckCorruption(
    94197    int abort_on_error              ///< Abort on detecting corruption?
    95198);
    96199
    97 /// Return reference counter
    98 int psMemGetRefCounter(
     200/** Return reference counter
     201 *
     202 *  @ingroup memRefCount
     203 */
     204psReferenceCount psMemGetRefCounter(
    99205    void *vptr                      ///< Pointer to get refCounter for
    100206);
    101207
    102 /// Increment reference counter and return the pointer
     208/** Increment reference counter and return the pointer
     209 *
     210 *  @ingroup memRefCount
     211 */
    103212void *psMemIncrRefCounter(
    104213    void *vptr                      ///< Pointer to increment refCounter, and return
    105214);
    106215
    107 /// Decrement reference counter and return the pointer
     216/** Decrement reference counter and return the pointer
     217 *
     218 *  @ingroup memRefCount
     219 */
    108220void *psMemDecrRefCounter(
    109221    void *vptr                      ///< Pointer to decrement refCounter, and return
    110222);
    111223
    112 /// Set callback for problems
     224/** Set callback for problems
     225 *  @ingroup memCallback
     226 */
    113227psMemProblemCallback psMemProblemCallbackSet(
    114228    psMemProblemCallback func       ///< Function to run
    115229);
    116230
    117 /// Set callback for out-of-memory
     231/** Set callback for out-of-memory
     232 *
     233 *  @ingroup memCallback
     234 */
    118235psMemExhaustedCallback psMemExhaustedCallbackSet(
    119236    psMemExhaustedCallback func     ///< Function to run
    120237);
    121238
    122 /// Set call back for when a particular memory block is allocated
     239/** Set call back for when a particular memory block is allocated
     240 *
     241 *  @ingroup memCallback
     242 */
    123243psMemAllocateCallback psMemAllocateCallbackSet(
    124     psMemAllocateCallback func      ///< Function to run
    125 );
    126 
    127 /// Set call back for when a particular memory block is freed
     244    psMemAllocateCallback func          ///< Function to run
     245);
     246
     247/** Set call back for when a particular memory block is freed
     248 *
     249 *  @ingroup memCallback
     250 */
    128251psMemFreeCallback psMemFreeCallbackSet(
    129     psMemFreeCallback func          ///< Function to run
    130 );
    131 
    132 /// get next memory ID
    133 int psMemGetId(void)
    134 ;
    135 
    136 /// set p_psMemAllocateID to id
    137 long psMemAllocateCallbackSetID(
    138     long id                         ///< ID to set
    139 );
    140 
    141 /// set p_psMemFreeID to id
    142 long psMemFreeCallbackSetID(
    143     long id                         ///< ID to set
    144 );
    145 
    146 //@} End of public Functions
    147 
    148 /// Memory allocation. psAlloc sends file and line number to p_psAlloc.
    149 #define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
    150 
    151 /// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
    152 #define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
    153 
    154 /// Free memory.  psFree sends file and line number to p_psFree.
    155 #define psFree(size) p_psFree(size, __FILE__, __LINE__)
     252    psMemFreeCallback func              ///< Function to run
     253);
     254
     255/** get next memory ID
     256 *
     257 *  @ingroup memCallback
     258 */
     259psMemoryId psMemGetId(void);
     260
     261/** set p_psMemAllocateID to id
     262 *
     263 *  @ingroup memCallback
     264 */
     265psMemoryId psMemAllocateCallbackSetID(
     266    psMemoryId id                       ///< ID to set
     267);
     268
     269/** set p_psMemFreeID to id
     270 *
     271 *  @ingroup memCallback
     272 */
     273psMemoryId psMemFreeCallbackSetID(
     274    psMemoryId id                       ///< ID to set
     275);
     276
     277//@} End of Memory Management Functions
     278
     279#ifndef DOXYGEN
    156280
    157281/*
     
    169293#endif
    170294
     295#endif // doxygen skip
     296
    171297#endif // end of header file
  • trunk/psLib/src/sysUtils/psMemory.c

    r639 r648  
    88 *  @author Robert Lupton, Princeton University
    99 *
    10  *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2004-05-11 20:11:17 $
     10 *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
     11 *  @date $Date: 2004-05-12 19:05:02 $
    1212 *
    1313 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2020#include <stdio.h>
    2121#include <stdbool.h>
     22#include <stdint.h>
    2223
    2324#include "psMemory.h"
     
    3435 * Unique ID for allocated blocks
    3536 */
    36 static unsigned long memid = 0;
     37static psMemoryId memid = 0;
    3738
    3839/**
     
    6263                                      const char *file, int lineno)
    6364{
    64     if (ptr->refCounter <= 0) {
     65    if (ptr->refCounter < 1) {
    6566        psError(__func__,
    6667                "Block %ld allocated at %s:%d freed more than once at %s:%d\n",
     
    9596 * Call the callbacks when these IDs are allocated/freed
    9697 */
    97 long p_psMemAllocateID = 0;  // notify user this block is allocated
    98 long p_psMemFreeID = 0;   // notify user this block is freed
    99 
    100 long psMemAllocateCallbackSetID(long id) // set p_psMemAllocateID to id
    101 {
    102     long old = p_psMemAllocateID;
     98psMemoryId p_psMemAllocateID = 0;  // notify user this block is allocated
     99psMemoryId p_psMemFreeID = 0;   // notify user this block is freed
     100
     101psMemoryId psMemAllocateCallbackSetID(psMemoryId id) // set p_psMemAllocateID to id
     102{
     103    psMemoryId old = p_psMemAllocateID;
    103104    p_psMemAllocateID = id;
    104105
     
    106107}
    107108
    108 long psMemFreeCallbackSetID(long id)  // set p_psMemFreeID to id
    109 {
    110     long old = p_psMemFreeID;
     109psMemoryId psMemFreeCallbackSetID(psMemoryId id)  // set p_psMemFreeID to id
     110{
     111    psMemoryId old = p_psMemFreeID;
    111112    p_psMemFreeID = id;
    112113
     
    120121 * isn't resignalled)
    121122 */
    122 static long memAllocateCallbackDefault(const psMemBlock *ptr)
    123 {
    124     static int incr = 0;  // "p_psMemAllocateID += incr"
     123static psMemoryId memAllocateCallbackDefault(const psMemBlock *ptr)
     124{
     125    static psMemoryId incr = 0;  // "p_psMemAllocateID += incr"
    125126
    126127    return incr;
    127128}
    128129
    129 static long memFreeCallbackDefault(const psMemBlock *ptr)
    130 {
    131     static int incr = 0;  // "p_psMemFreeID += incr"
     130static psMemoryId memFreeCallbackDefault(const psMemBlock *ptr)
     131{
     132    static psMemoryId incr = 0;  // "p_psMemFreeID += incr"
    132133
    133134    return incr;
     
    169170 * Return memory ID counter for next block to be allocated
    170171 */
    171 int psMemGetId(void)
     172psMemoryId psMemGetId(void)
    172173{
    173174    return memid + 1;
     
    199200
    200201    if (m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {
    201         psError(funcName, "psMemCheckCorruption: memory block %ld is corrupted (%p %p)",
     202        psError(funcName, "psMemCheckCorruption: memory block %ld is corrupted (buffer underflow %p %p)",
    202203                m->id,m->startblock,m->endblock);
     204        return(1);
     205    }
     206    if (*(void**)((int8_t*)(m+1)+m->userMemorySize) != P_PS_MEMMAGIC) {
     207        psError(funcName, "psMemCheckCorruption: memory block %ld is corrupted (buffer overflow, %p)",
     208                m->id,*(void**)((int8_t*)(m+1)+m->userMemorySize));
    203209        return(1);
    204210    }
     
    236242void *p_psAlloc(size_t size, const char *file, int lineno)
    237243{
    238     psMemBlock *ptr = malloc(sizeof(psMemBlock) + size);
     244    psMemBlock *ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));
    239245
    240246    if (ptr == NULL) {
     
    246252    }
    247253
    248     *(unsigned long*)&ptr->id = ++memid;
     254    *(psMemoryId*)&ptr->id = ++memid;
    249255    ptr->file = file;
    250256    *(unsigned int*)&ptr->lineno = lineno;
     
    252258    ptr->endblock = P_PS_MEMMAGIC;
    253259    ptr->refCounter = 1;                // one user so far
     260    ptr->userMemorySize = size;
     261    *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;
    254262
    255263    // need exclusive access of the memory block list now...
     
    287295        isBlockLast = (ptr == lastMemBlockAllocated);
    288296
    289         ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size);
     297        ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size + sizeof(void*));
    290298
    291299        if (ptr == NULL) {
     
    293301                    size, file, lineno);
    294302        }
     303
     304        ptr->userMemorySize = size;
     305        *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;
    295306
    296307        if (isBlockLast) {
     
    363374 */
    364375int psMemCheckLeaks(
    365     int id0,                            // don't list blocks with id < id0
     376    psMemoryId id0,                     // don't list blocks with id < id0
    366377    psMemBlock ***arr,                  // pointer to array of pointers to leaked blocks, or NULL
    367378    FILE *fd)                           // print list of leaks to fd (or NULL)
     
    416427 * Reference counting APIs
    417428 */
    418 int psMemGetRefCounter(void *vptr) // return refCounter
     429psReferenceCount psMemGetRefCounter(void *vptr) // return refCounter
    419430{
    420431    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
  • trunk/psLib/src/sysUtils/psMemory.h

    r639 r648  
    1212 *  @author Robert Lupton, Princeton University
    1313 *
    14  *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
    15  *  @date $Date: 2004-05-11 20:11:17 $
     14 *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
     15 *  @date $Date: 2004-05-12 19:05:02 $
     16 *
     17 *  @ingroup SystemGroup System Utilities
    1618 *
    1719 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1921
    2022#include <stdio.h>                      // needed for FILE
     23
     24
     25/** @addtogroup MemoryManagement Memory Management Utilities
     26 *  @ingroup SystemGroup
     27 *
     28 *  This is the generic memory management system put inbetween the user's high level code and the OS-level
     29 *  memory allocation routines.  This system adds such features as callback routines for memory error events,
     30 *  tracing capabilities, and reference counting.
     31 *  @{
     32 */
     33
     34/**
     35 *  @addtogroup memCallback Memory Callbacks
     36 *
     37 *  Routines dealing with the creating and setting of memory management callback functions.
     38 */
     39
     40/**
     41 *  @addtogroup memRefCount Reference Count
     42 *
     43 *  Routines dealing with the reference counting of allocated buffers.
     44 */
     45
     46/// typedef for memory identification numbers.  Guaranteed to be some variety of integer.
     47typedef unsigned long psMemoryId;
     48
     49/// typedef for a memory block's reference count. Guaranteed to be some variety of integer.
     50typedef unsigned long psReferenceCount;
    2151
    2252/** Book-keeping data for storage allocator.
     
    3060    struct psMemBlock* previousBlock;   ///< previous block in allocation list
    3161    struct psMemBlock* nextBlock;       ///< next block allocation list
    32     const unsigned long id;             ///< a unique ID for this allocation
     62    size_t  userMemorySize;             ///< the size of the user-portion of the memory block
     63    const psMemoryId id;                ///< a unique ID for this allocation
    3364    const char* file;                   ///< set from __FILE__ in e.g. p_psAlloc
    3465    const int lineno;                   ///< set from __LINE__ in e.g. p_psAlloc
    35     unsigned int refCounter;            ///< how many times pointer is referenced
     66    psReferenceCount refCounter;            ///< how many times pointer is referenced
    3667    const void* endblock;               ///< initialised to p_psMEMMAGIC
    3768}
    3869psMemBlock;
    3970
    40 /// prototype of a basic callback used by memory functions
    41 typedef long (*psMemAllocateCallback)(const psMemBlock *ptr);
    42 
    43 /// prototype of memory free callback used by memory functions
    44 typedef long (*psMemFreeCallback)(const psMemBlock *ptr);
     71/** prototype of a basic callback used by memory functions
     72 *
     73 *  @see psMemAllocateCallbackSet
     74 *  @ingroup memCallback
     75 */
     76typedef psMemoryId (*psMemAllocateCallback)(
     77    const psMemBlock *ptr           ///< the psMemBlock just allocated
     78);
     79
     80/** prototype of memory free callback used by memory functions
     81 *
     82 *  @see psMemFreeCallbackSet
     83 *  @ingroup memCallback
     84 */
     85typedef psMemoryId (*psMemFreeCallback)(
     86    const psMemBlock *ptr           ///< the psMemBlock being freed
     87);
    4588
    4689/** prototype of a callback used in error conditions
    4790 *
    48  *  This callback should never try to call psAlloc or psFree.
    49  *
    50  */
    51 typedef void (*psMemProblemCallback)(const psMemBlock *ptr, const char *file, int lineno);
    52 
    53 /// prototype of a callback used when memory runs out
    54 typedef void *(*psMemExhaustedCallback)(size_t size);
    55 
    56 /** Private Functions **************************************************************/
    57 /** \addtogroup sysUtils memory private
    58  *  \{
    59  */
    60 
    61 /// Memory allocation. Underlying private function called by macro psAlloc.
    62 void* p_psAlloc(size_t size,  ///< Size required
    63                 const char *file, ///< File of call
    64                 int lineno)  ///< Line number of call
    65 ;
    66 
    67 /// Memory re-allocation.  Underlying private function called by macro psRealloc.
    68 void* p_psRealloc(void *ptr,  ///< Pointer to re-allocate
    69                   size_t size,  ///< Size required
    70                   const char *file, ///< File of call
    71                   int lineno)  ///< Line number of call
    72 ;
    73 
    74 /// Free memory.  Underlying private function called by macro psFree.
    75 void p_psFree(void *ptr,  ///< Pointer to free
    76               const char *file,  ///< File of call
    77               int lineno)  ///< Line number of call
    78 ;
    79 /** Public Functions **************************************************************/
    80 /** \}
    81  *  \addtogroup sysUtils memory psLibAPI
    82  *  \{
    83  */
    84 
    85 /// Check for memory leaks
     91 *  This callback should not try to call psAlloc or psFree.
     92 *
     93 *  @see psMemProblemCallbackSet
     94 *  @ingroup memCallback
     95 */
     96typedef void (*psMemProblemCallback)(
     97    const psMemBlock *ptr,          ///< the pointer to the problematic memory block.
     98    const char *file,               ///< the file in which the problem originated
     99    int lineno                      ///< the line number in which the problem originated
     100);
     101
     102/** prototype of a callback function used when memory runs out
     103 *
     104 *  @return void* pointer to requested buffer of the size size_t, or NULL if memory could not
     105 *          be found.
     106 *
     107 *  @see psMemExhaustedCallbackSet
     108 *  @ingroup memCallback
     109 */
     110typedef void *(*psMemExhaustedCallback)(
     111    size_t size                     //< the size of buffer required
     112);
     113
     114/** Memory allocation.  This operates much like malloc(), but is guaranteed to return a non-NULL value.
     115 *
     116 *  @return void* pointer to the allocated buffer. This will not be NULL.
     117 *  @see psFree
     118 */
     119#ifdef DOXYGEN
     120void* psAlloc(
     121    size_t size                     ///< Size required
     122);
     123#else
     124void* p_psAlloc(
     125    size_t size,                    ///< Size required
     126    const char *file,               ///< File of call
     127    int lineno                      ///< Line number of call
     128);
     129/// Memory allocation. psAlloc sends file and line number to p_psAlloc.
     130#define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
     131#endif
     132
     133
     134/** Memory re-allocation.  This operates much like realloc(), but is guaranteed to return a non-NULL value.
     135 *
     136 *  @return void* pointer to resized buffer. This will not be NULL.
     137 *  @see psAlloc, psFree
     138 */
     139#ifdef DOXYGEN
     140void* psRealloc(void *ptr               ///< Pointer to re-allocate
     141               );
     142#else
     143void* p_psRealloc(void *ptr,            ///< Pointer to re-allocate
     144                  size_t size,          ///< Size required
     145                  const char *file,     ///< File of call
     146                  int lineno            ///< Line number of call
     147                 );
     148
     149/// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
     150#define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
     151
     152#endif
     153
     154
     155/** Free memory.  This operates much like free().
     156 *
     157 *  @see psAlloc, psRealloc
     158 */
     159#ifdef DOXYGEN
     160void psFree(void *ptr,                  ///< Pointer to free, if NULL, function returns immediately.
     161           );
     162#else
     163void p_psFree(void *ptr,                ///< Pointer to free
     164              const char *file,         ///< File of call
     165              int lineno                ///< Line number of call
     166             );
     167
     168/// Free memory.  psFree sends file and line number to p_psFree.
     169#define psFree(size) p_psFree(size, __FILE__, __LINE__)
     170
     171#endif
     172
     173/** Check for memory leaks.  This scans for allocated memory buffers not freed with an ID not less than id0.
     174 *  This is used to check for memory leaks by:
     175 *      -# before a block of code to be checked, store the current ID count via psGetMemId
     176 *      -# after the block of code to be checked, call this function using the ID stored above.  If all
     177 *         memory in the block that was allocated has been freed, this call should output nothing and
     178 *         return 0.
     179 *
     180 *  If memory leaks are found, the Memory Problem callback will be called as well.
     181 *
     182 *  return int  number of memory blocks found as 'leaks', i.e., the number of currently allocated memory
     183 *              blocks above id0 that have not been freed.
     184 *  @see psAlloc, psFree, psgetMemId, psMemProblemCallbackSet
     185 */
    86186int psMemCheckLeaks(
    87     int id0,                        ///< don't list blocks with id < id0
     187    psMemoryId id0,              ///< don't list blocks with id < id0
    88188    psMemBlock ***arr,              ///< pointer to array of pointers to leaked blocks, or NULL
    89189    FILE *fd                        ///< print list of leaks to fd (or NULL)
    90190);
    91191
    92 /// Check for memory corruption
     192/** Check for memory corruption.  Scans all currently allocated memory buffers and checks for corruptions,
     193 *  i.e., invalid markers that signify a buffer under/overflow.
     194 *
     195 */
    93196int psMemCheckCorruption(
    94197    int abort_on_error              ///< Abort on detecting corruption?
    95198);
    96199
    97 /// Return reference counter
    98 int psMemGetRefCounter(
     200/** Return reference counter
     201 *
     202 *  @ingroup memRefCount
     203 */
     204psReferenceCount psMemGetRefCounter(
    99205    void *vptr                      ///< Pointer to get refCounter for
    100206);
    101207
    102 /// Increment reference counter and return the pointer
     208/** Increment reference counter and return the pointer
     209 *
     210 *  @ingroup memRefCount
     211 */
    103212void *psMemIncrRefCounter(
    104213    void *vptr                      ///< Pointer to increment refCounter, and return
    105214);
    106215
    107 /// Decrement reference counter and return the pointer
     216/** Decrement reference counter and return the pointer
     217 *
     218 *  @ingroup memRefCount
     219 */
    108220void *psMemDecrRefCounter(
    109221    void *vptr                      ///< Pointer to decrement refCounter, and return
    110222);
    111223
    112 /// Set callback for problems
     224/** Set callback for problems
     225 *  @ingroup memCallback
     226 */
    113227psMemProblemCallback psMemProblemCallbackSet(
    114228    psMemProblemCallback func       ///< Function to run
    115229);
    116230
    117 /// Set callback for out-of-memory
     231/** Set callback for out-of-memory
     232 *
     233 *  @ingroup memCallback
     234 */
    118235psMemExhaustedCallback psMemExhaustedCallbackSet(
    119236    psMemExhaustedCallback func     ///< Function to run
    120237);
    121238
    122 /// Set call back for when a particular memory block is allocated
     239/** Set call back for when a particular memory block is allocated
     240 *
     241 *  @ingroup memCallback
     242 */
    123243psMemAllocateCallback psMemAllocateCallbackSet(
    124     psMemAllocateCallback func      ///< Function to run
    125 );
    126 
    127 /// Set call back for when a particular memory block is freed
     244    psMemAllocateCallback func          ///< Function to run
     245);
     246
     247/** Set call back for when a particular memory block is freed
     248 *
     249 *  @ingroup memCallback
     250 */
    128251psMemFreeCallback psMemFreeCallbackSet(
    129     psMemFreeCallback func          ///< Function to run
    130 );
    131 
    132 /// get next memory ID
    133 int psMemGetId(void)
    134 ;
    135 
    136 /// set p_psMemAllocateID to id
    137 long psMemAllocateCallbackSetID(
    138     long id                         ///< ID to set
    139 );
    140 
    141 /// set p_psMemFreeID to id
    142 long psMemFreeCallbackSetID(
    143     long id                         ///< ID to set
    144 );
    145 
    146 //@} End of public Functions
    147 
    148 /// Memory allocation. psAlloc sends file and line number to p_psAlloc.
    149 #define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
    150 
    151 /// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
    152 #define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
    153 
    154 /// Free memory.  psFree sends file and line number to p_psFree.
    155 #define psFree(size) p_psFree(size, __FILE__, __LINE__)
     252    psMemFreeCallback func              ///< Function to run
     253);
     254
     255/** get next memory ID
     256 *
     257 *  @ingroup memCallback
     258 */
     259psMemoryId psMemGetId(void);
     260
     261/** set p_psMemAllocateID to id
     262 *
     263 *  @ingroup memCallback
     264 */
     265psMemoryId psMemAllocateCallbackSetID(
     266    psMemoryId id                       ///< ID to set
     267);
     268
     269/** set p_psMemFreeID to id
     270 *
     271 *  @ingroup memCallback
     272 */
     273psMemoryId psMemFreeCallbackSetID(
     274    psMemoryId id                       ///< ID to set
     275);
     276
     277//@} End of Memory Management Functions
     278
     279#ifndef DOXYGEN
    156280
    157281/*
     
    169293#endif
    170294
     295#endif // doxygen skip
     296
    171297#endif // end of header file
Note: See TracChangeset for help on using the changeset viewer.