IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 451


Ignore:
Timestamp:
Apr 19, 2004, 10:14:04 AM (22 years ago)
Author:
desonia
Message:

updated the memory management to keep track of the memory via double-linked-listing the blocks together.

Location:
trunk/psLib/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/sys/psMemory.c

    r432 r451  
    88 *  @author Robert Lupton, Princeton University
    99 *
    10  *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2004-04-16 02:18:57 $
     10 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
     11 *  @date $Date: 2004-04-19 20:14:04 $
    1212 *
    1313 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1616#define PS_ALLOW_MALLOC                 // we're allowed to call malloc()
    1717
     18#include <pthread.h>                   // we need a mutex to make this stuff thread safe.
    1819#include <stdlib.h>
    1920#include <stdio.h>
     
    2526
    2627static int checkMemBlock(const psMemBlock *m, const char* funcName);
    27 static int numMemBlock = 0;             // size of memBlocks
    28 static psMemBlock **memBlocks = NULL;
     28static psMemBlock *lastMemBlockAllocated = NULL;
     29pthread_mutex_t   memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
    2930
    3031/**
     
    183184
    184185static int
    185 checkMemBlock(const psMemBlock *m, // block to check
    186              const char* funcName)   // be quiet?
    187 {
     186checkMemBlock(const psMemBlock *m,
     187             const char* funcName)
     188{
     189    // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked,
     190    // we shouldn't call such things as p_psAlloc/p_psFree here.
     191
    188192    if (m == NULL) {
    189193        psError(funcName,"Memory Corruption: NULL memory block found.");
     
    206210int psMemCheckCorruption(int abort_on_error)
    207211{
    208     int nbad = 0;   // number of bad blocks
    209 
    210     if (memBlocks == NULL) {
    211         return 0;   // no memory is allocated to be corrupted
    212     }
    213 
    214     for (int i = 1; i <= memid; i++) {
    215         if (memBlocks[i] != NULL) {
    216             if (checkMemBlock(memBlocks[i], __func__)) {
    217                 nbad++;
    218 
    219                 memProblemCallback(memBlocks[i], __func__, __LINE__);
    220 
    221                 if (abort_on_error) {
    222                     psAbort(__func__, "Detected memory corruption");
    223                 }
    224             }
     212    int nbad = 0;                       // number of bad blocks
     213
     214        // get exclusive access to the memBlock list to avoid it changing on us while we use it.
     215        pthread_mutex_lock(&memBlockListMutex);
     216
     217    for (psMemBlock* iter=lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock)
     218{
     219        if (checkMemBlock(iter, __func__)) {
     220                        nbad++;
     221
     222                        memProblemCallback(iter, __func__, __LINE__);
     223
     224                        if (abort_on_error) {
     225                                // release the lock on the memblock list
     226                pthread_mutex_unlock(&memBlockListMutex);
     227                                psAbort(__func__, "Detected memory corruption");
     228                                return nbad;
     229                        }
    225230        }
    226231    }
    227232
     233        // release the lock on the memblock list
     234        pthread_mutex_unlock(&memBlockListMutex);
    228235    return nbad;
    229236}
     
    243250    }
    244251
    245     *(unsigned long *)&ptr->id = ++memid;
     252    *(unsigned long*)&ptr->id = ++memid;
    246253    ptr->file = file;
    247     *(int *)&ptr->lineno = lineno;
     254    *(unsigned int*)&ptr->lineno = lineno;
    248255    ptr->startblock = P_PS_MEMMAGIC;
    249256        ptr->endblock = P_PS_MEMMAGIC;
    250 
    251     ptr->refCounter = 1;  // one user so far
    252     /*
    253      * Did the user ask to be informed about this allocation?
    254      */
    255 
    256     if (ptr->id == p_psMemAllocateID && p_psMemAllocateID > 0) {
     257    ptr->refCounter = 1;                // one user so far
     258
     259        // need exclusive access of the memory block list now...
     260        pthread_mutex_lock(&memBlockListMutex);
     261
     262        // insert the new block to the front of the memBlock linked-list
     263        ptr->previousBlock = NULL;
     264        ptr->nextBlock = lastMemBlockAllocated;
     265        if (ptr->nextBlock != NULL) {
     266            ptr->nextBlock->previousBlock = ptr;
     267        }
     268        lastMemBlockAllocated = ptr;
     269
     270        pthread_mutex_unlock(&memBlockListMutex);
     271
     272    //  Did the user ask to be informed about this allocation?
     273    if (ptr->id == p_psMemAllocateID) {
    257274        p_psMemAllocateID += memAllocateCallback(ptr);
    258275    }
    259     if (memid >= numMemBlock) {
    260         numMemBlock = (numMemBlock == 0) ? 100000 : 2*numMemBlock;
    261         memBlocks = realloc(memBlocks, numMemBlock*sizeof(psMemBlock *)); // NOT psRealloc
    262     }
    263     memBlocks[ptr->id] = ptr;
    264     /*
    265      * And return the user the memory that they allocated
    266      */
    267     return ptr + 1;   // usr memory
     276
     277        // And return the user the memory that they allocated
     278    return ptr + 1;   // user memory
    268279}
    269280
     
    274285    } else {
    275286        psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    276         ptr = (psMemBlock *)realloc(ptr, sizeof(psMemBlock) + size);
    277         memBlocks[ptr->id] = ptr;
    278 
    279         return ptr + 1;   // usr memory
     287
     288        pthread_mutex_lock(&memBlockListMutex);
     289
     290                ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size);
     291
     292                // the block location may have changed, so fix the linked list addresses.
     293                if (ptr->nextBlock != NULL) {
     294                    ptr->nextBlock->previousBlock = ptr;
     295                }
     296                if (ptr->previousBlock != NULL) {
     297                    ptr->previousBlock->nextBlock = ptr;
     298                }
     299
     300            pthread_mutex_unlock(&memBlockListMutex);
     301
     302                return ptr + 1;   // usr memory
    280303    }
    281304}
     
    288311
    289312    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    290     /*
    291      * Did the user ask to be informed about this deallocation?
    292      */
    293     if (ptr->id == p_psMemFreeID && p_psMemFreeID > 0) {
     313
     314        // Did the user ask to be informed about this deallocation?
     315    if (ptr->id == p_psMemFreeID) {
    294316        p_psMemFreeID += memFreeCallback(ptr);
    295317    }
     
    298320        memProblemCallback(ptr, file, lineno); // we may not own this block; don't free it
    299321    } else {
    300         if (ptr->refCounter != 1) {
     322        if (ptr->refCounter > 1) {
     323                    psError(__func__,"The buffer being freed is referenced elsewhere. "
     324                                "Buffer's reference count was decremented instead.");
     325            ptr->refCounter--;
    301326            memProblemCallback(ptr, file, lineno);
     327        } else {
     328
     329                        // cut the memBlock out of the memBlock list
     330                pthread_mutex_lock(&memBlockListMutex);
     331                        if (ptr->nextBlock != NULL) {
     332                            ptr->nextBlock->previousBlock = ptr->previousBlock;
     333                        }
     334                        if (ptr->previousBlock != NULL) {
     335                            ptr->previousBlock->nextBlock = ptr->nextBlock;
     336                        }
     337                        if (lastMemBlockAllocated == ptr) {
     338                            lastMemBlockAllocated = ptr->nextBlock;
     339                        }
     340
     341                pthread_mutex_unlock(&memBlockListMutex);
     342
     343                    free(ptr);
     344                }
     345    }
     346}
     347
     348/*****************************************************************************/
     349/*
     350 * Check for memory leaks. Not production quality code
     351 */
     352int psMemCheckLeaks(
     353    int id0,                            // don't list blocks with id < id0
     354    psMemBlock ***arr,                  // pointer to array of pointers to leaked blocks, or NULL
     355    FILE *fd)                           // print list of leaks to fd (or NULL)
     356{
     357    int nleak = 0;
     358        int j = 0;
     359
     360        pthread_mutex_lock(&memBlockListMutex);
     361
     362    for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {
     363        if ( (iter->refCounter > 0) && (iter->id >= id0) ) {
     364                        nleak++;
     365
     366                        if (fd != NULL) {
     367                                if (nleak == 1) {
     368                                        fprintf(fd, "   %20s:line ID\n", "file");
     369                                }
     370
     371                                fprintf(fd, "   %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);
     372                        }
     373                }
     374    }
     375
     376        pthread_mutex_unlock(&memBlockListMutex);
     377
     378        if (nleak == 0 || arr == NULL) {
     379        return nleak;
     380    }
     381
     382    p_psFree(*arr,__FILE__, __LINE__);  // Don't generate a memory leak!
     383
     384    *arr = p_psAlloc(nleak*sizeof(psMemBlock), __FILE__, __LINE__);
     385
     386        pthread_mutex_lock(&memBlockListMutex);
     387
     388    for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {
     389        if ( (iter->refCounter > 0) && (iter->id >= id0) ) {
     390                        (*arr)[j++] = iter;
     391                        if (j == nleak) { // found them all
     392                                break;
     393                        }
    302394        }
    303         ptr->refCounter--;
    304         #if 1
    305 
    306         memBlocks[ptr->id] = NULL; // XXX sub-optimal! Can't check
    307         // freed blocks for corruption/double frees
    308         free(ptr);
    309         #endif
    310 
    311     }
    312 }
    313 
    314 /*****************************************************************************/
    315 /*
    316  * Check for memory leaks. Not production quality code
    317  */
    318 int psMemCheckLeaks(
    319     int id0,    // don't list blocks with id < id0
    320     psMemBlock ***arr,   // pointer to array of pointers to
    321     // leaked blocks, or NULL
    322     FILE *fd)    // print list of leaks to fd (or NULL)
    323 {
    324     int nleak = 0;
    325 
    326     if (memBlocks == NULL)
    327     {  // nothing was allocated
    328         return 0;
    329     }
    330 
    331     for (int i = id0; i <= memid; i++)
    332     {
    333         if (memBlocks[i] != NULL) {
    334             if (memBlocks[i]->refCounter > 0) {
    335                 nleak++;
    336 
    337                 if (fd != NULL) {
    338                     if (nleak == 1) {
    339                         fprintf(fd, "   %20s:line ID\n", "file");
    340                     }
    341 
    342                     fprintf(fd, "   %20s:%-4d %ld\n",
    343                             memBlocks[i]->file, memBlocks[i]->lineno,
    344                             memBlocks[i]->id);
    345                 }
    346             }
    347         }
    348     }
    349 
    350     if (nleak == 0 || arr == NULL)
    351     {
    352         return nleak;
    353     }
    354 
    355     p_psFree(*arr,__FILE__, __LINE__);  // Don't generate a memory leak!
    356 
    357     *arr = p_psAlloc(nleak*sizeof(psMemBlock), __FILE__, __LINE__);
    358     for (int i = id0, j = 0; i < memid; i++)
    359     {
    360         if (memBlocks[i] != NULL) {
    361             if (memBlocks[i]->refCounter > 0) {
    362                 (*arr)[j++] = memBlocks[i];
    363                 if (j == nleak) { // found them all
    364                     break;
    365                 }
    366             }
    367         }
    368     }
     395    }
     396
     397    pthread_mutex_unlock(&memBlockListMutex);
    369398
    370399    return nleak;
     
    389418void *psMemIncrRefCounter(void *vptr) // increment and return refCounter
    390419{
    391     if (vptr == NULL)
    392     {
     420    if (vptr == NULL) {
    393421        return vptr;
    394422    }
     
    396424    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    397425
    398     if (checkMemBlock(ptr, __func__))
    399     {
     426    if (checkMemBlock(ptr, __func__)) {
    400427        memProblemCallback(ptr, __func__, __LINE__);
    401428    }
     
    408435void *psMemDecrRefCounter(void *vptr) // decrement and return refCounter
    409436{
    410     if (vptr == NULL)
    411     {
     437    if (vptr == NULL) {
    412438        return vptr;
    413439    }
     
    415441    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    416442
    417     if (checkMemBlock(ptr, __func__))
    418     {
     443    if (checkMemBlock(ptr, __func__)) {
    419444        memProblemCallback(ptr, __func__, __LINE__);
    420445    }
  • trunk/psLib/src/sys/psMemory.h

    r432 r451  
    1414 *  @author Robert Lupton, Princeton University
    1515 *
    16  *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
    17  *  @date $Date: 2004-04-16 02:18:57 $
     16 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
     17 *  @date $Date: 2004-04-19 20:14:04 $
    1818 *
    1919 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2525 *  aligned for all storage types.
    2626 */
    27 typedef struct
     27typedef struct psMemBlock
    2828{
    29     const void *startblock;             ///< initialised to p_psMEMMAGIC
     29    const void* startblock;             ///< initialised to p_psMEMMAGIC
     30        struct psMemBlock* previousBlock;   ///< previous block in allocation list
     31        struct psMemBlock* nextBlock;       ///< next block allocation list
    3032    const unsigned long id;             ///< a unique ID for this allocation
    31     const char *file;                   ///< set from __FILE__ in e.g. p_psAlloc
     33    const char* file;                   ///< set from __FILE__ in e.g. p_psAlloc
    3234    const int lineno;                   ///< set from __LINE__ in e.g. p_psAlloc
    33     int refCounter;                     ///< how many times pointer is referenced
    34     const void **endpost;               ///< initialised to p_psMEMMAGIC
    35     const void *endblock;               ///< initialised to p_psMEMMAGIC
     35    unsigned int refCounter;            ///< how many times pointer is referenced
     36    const void* endblock;               ///< initialised to p_psMEMMAGIC
    3637}
    3738psMemBlock;
     
    4344typedef long (*psMemFreeCallback)(const psMemBlock *ptr);
    4445
    45 /// prototype of a callback used in error conditions
     46/** prototype of a callback used in error conditions
     47 *
     48 *  This callback should never try to call psAlloc or psFree.
     49 *
     50 */
    4651typedef void (*psMemProblemCallback)(const psMemBlock *ptr, const char *file, int lineno);
    4752
  • trunk/psLib/src/sysUtils/psMemory.c

    r432 r451  
    88 *  @author Robert Lupton, Princeton University
    99 *
    10  *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2004-04-16 02:18:57 $
     10 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
     11 *  @date $Date: 2004-04-19 20:14:04 $
    1212 *
    1313 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1616#define PS_ALLOW_MALLOC                 // we're allowed to call malloc()
    1717
     18#include <pthread.h>                   // we need a mutex to make this stuff thread safe.
    1819#include <stdlib.h>
    1920#include <stdio.h>
     
    2526
    2627static int checkMemBlock(const psMemBlock *m, const char* funcName);
    27 static int numMemBlock = 0;             // size of memBlocks
    28 static psMemBlock **memBlocks = NULL;
     28static psMemBlock *lastMemBlockAllocated = NULL;
     29pthread_mutex_t   memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
    2930
    3031/**
     
    183184
    184185static int
    185 checkMemBlock(const psMemBlock *m, // block to check
    186              const char* funcName)   // be quiet?
    187 {
     186checkMemBlock(const psMemBlock *m,
     187             const char* funcName)
     188{
     189    // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked,
     190    // we shouldn't call such things as p_psAlloc/p_psFree here.
     191
    188192    if (m == NULL) {
    189193        psError(funcName,"Memory Corruption: NULL memory block found.");
     
    206210int psMemCheckCorruption(int abort_on_error)
    207211{
    208     int nbad = 0;   // number of bad blocks
    209 
    210     if (memBlocks == NULL) {
    211         return 0;   // no memory is allocated to be corrupted
    212     }
    213 
    214     for (int i = 1; i <= memid; i++) {
    215         if (memBlocks[i] != NULL) {
    216             if (checkMemBlock(memBlocks[i], __func__)) {
    217                 nbad++;
    218 
    219                 memProblemCallback(memBlocks[i], __func__, __LINE__);
    220 
    221                 if (abort_on_error) {
    222                     psAbort(__func__, "Detected memory corruption");
    223                 }
    224             }
     212    int nbad = 0;                       // number of bad blocks
     213
     214        // get exclusive access to the memBlock list to avoid it changing on us while we use it.
     215        pthread_mutex_lock(&memBlockListMutex);
     216
     217    for (psMemBlock* iter=lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock)
     218{
     219        if (checkMemBlock(iter, __func__)) {
     220                        nbad++;
     221
     222                        memProblemCallback(iter, __func__, __LINE__);
     223
     224                        if (abort_on_error) {
     225                                // release the lock on the memblock list
     226                pthread_mutex_unlock(&memBlockListMutex);
     227                                psAbort(__func__, "Detected memory corruption");
     228                                return nbad;
     229                        }
    225230        }
    226231    }
    227232
     233        // release the lock on the memblock list
     234        pthread_mutex_unlock(&memBlockListMutex);
    228235    return nbad;
    229236}
     
    243250    }
    244251
    245     *(unsigned long *)&ptr->id = ++memid;
     252    *(unsigned long*)&ptr->id = ++memid;
    246253    ptr->file = file;
    247     *(int *)&ptr->lineno = lineno;
     254    *(unsigned int*)&ptr->lineno = lineno;
    248255    ptr->startblock = P_PS_MEMMAGIC;
    249256        ptr->endblock = P_PS_MEMMAGIC;
    250 
    251     ptr->refCounter = 1;  // one user so far
    252     /*
    253      * Did the user ask to be informed about this allocation?
    254      */
    255 
    256     if (ptr->id == p_psMemAllocateID && p_psMemAllocateID > 0) {
     257    ptr->refCounter = 1;                // one user so far
     258
     259        // need exclusive access of the memory block list now...
     260        pthread_mutex_lock(&memBlockListMutex);
     261
     262        // insert the new block to the front of the memBlock linked-list
     263        ptr->previousBlock = NULL;
     264        ptr->nextBlock = lastMemBlockAllocated;
     265        if (ptr->nextBlock != NULL) {
     266            ptr->nextBlock->previousBlock = ptr;
     267        }
     268        lastMemBlockAllocated = ptr;
     269
     270        pthread_mutex_unlock(&memBlockListMutex);
     271
     272    //  Did the user ask to be informed about this allocation?
     273    if (ptr->id == p_psMemAllocateID) {
    257274        p_psMemAllocateID += memAllocateCallback(ptr);
    258275    }
    259     if (memid >= numMemBlock) {
    260         numMemBlock = (numMemBlock == 0) ? 100000 : 2*numMemBlock;
    261         memBlocks = realloc(memBlocks, numMemBlock*sizeof(psMemBlock *)); // NOT psRealloc
    262     }
    263     memBlocks[ptr->id] = ptr;
    264     /*
    265      * And return the user the memory that they allocated
    266      */
    267     return ptr + 1;   // usr memory
     276
     277        // And return the user the memory that they allocated
     278    return ptr + 1;   // user memory
    268279}
    269280
     
    274285    } else {
    275286        psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    276         ptr = (psMemBlock *)realloc(ptr, sizeof(psMemBlock) + size);
    277         memBlocks[ptr->id] = ptr;
    278 
    279         return ptr + 1;   // usr memory
     287
     288        pthread_mutex_lock(&memBlockListMutex);
     289
     290                ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size);
     291
     292                // the block location may have changed, so fix the linked list addresses.
     293                if (ptr->nextBlock != NULL) {
     294                    ptr->nextBlock->previousBlock = ptr;
     295                }
     296                if (ptr->previousBlock != NULL) {
     297                    ptr->previousBlock->nextBlock = ptr;
     298                }
     299
     300            pthread_mutex_unlock(&memBlockListMutex);
     301
     302                return ptr + 1;   // usr memory
    280303    }
    281304}
     
    288311
    289312    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    290     /*
    291      * Did the user ask to be informed about this deallocation?
    292      */
    293     if (ptr->id == p_psMemFreeID && p_psMemFreeID > 0) {
     313
     314        // Did the user ask to be informed about this deallocation?
     315    if (ptr->id == p_psMemFreeID) {
    294316        p_psMemFreeID += memFreeCallback(ptr);
    295317    }
     
    298320        memProblemCallback(ptr, file, lineno); // we may not own this block; don't free it
    299321    } else {
    300         if (ptr->refCounter != 1) {
     322        if (ptr->refCounter > 1) {
     323                    psError(__func__,"The buffer being freed is referenced elsewhere. "
     324                                "Buffer's reference count was decremented instead.");
     325            ptr->refCounter--;
    301326            memProblemCallback(ptr, file, lineno);
     327        } else {
     328
     329                        // cut the memBlock out of the memBlock list
     330                pthread_mutex_lock(&memBlockListMutex);
     331                        if (ptr->nextBlock != NULL) {
     332                            ptr->nextBlock->previousBlock = ptr->previousBlock;
     333                        }
     334                        if (ptr->previousBlock != NULL) {
     335                            ptr->previousBlock->nextBlock = ptr->nextBlock;
     336                        }
     337                        if (lastMemBlockAllocated == ptr) {
     338                            lastMemBlockAllocated = ptr->nextBlock;
     339                        }
     340
     341                pthread_mutex_unlock(&memBlockListMutex);
     342
     343                    free(ptr);
     344                }
     345    }
     346}
     347
     348/*****************************************************************************/
     349/*
     350 * Check for memory leaks. Not production quality code
     351 */
     352int psMemCheckLeaks(
     353    int id0,                            // don't list blocks with id < id0
     354    psMemBlock ***arr,                  // pointer to array of pointers to leaked blocks, or NULL
     355    FILE *fd)                           // print list of leaks to fd (or NULL)
     356{
     357    int nleak = 0;
     358        int j = 0;
     359
     360        pthread_mutex_lock(&memBlockListMutex);
     361
     362    for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {
     363        if ( (iter->refCounter > 0) && (iter->id >= id0) ) {
     364                        nleak++;
     365
     366                        if (fd != NULL) {
     367                                if (nleak == 1) {
     368                                        fprintf(fd, "   %20s:line ID\n", "file");
     369                                }
     370
     371                                fprintf(fd, "   %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);
     372                        }
     373                }
     374    }
     375
     376        pthread_mutex_unlock(&memBlockListMutex);
     377
     378        if (nleak == 0 || arr == NULL) {
     379        return nleak;
     380    }
     381
     382    p_psFree(*arr,__FILE__, __LINE__);  // Don't generate a memory leak!
     383
     384    *arr = p_psAlloc(nleak*sizeof(psMemBlock), __FILE__, __LINE__);
     385
     386        pthread_mutex_lock(&memBlockListMutex);
     387
     388    for (psMemBlock* iter = lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {
     389        if ( (iter->refCounter > 0) && (iter->id >= id0) ) {
     390                        (*arr)[j++] = iter;
     391                        if (j == nleak) { // found them all
     392                                break;
     393                        }
    302394        }
    303         ptr->refCounter--;
    304         #if 1
    305 
    306         memBlocks[ptr->id] = NULL; // XXX sub-optimal! Can't check
    307         // freed blocks for corruption/double frees
    308         free(ptr);
    309         #endif
    310 
    311     }
    312 }
    313 
    314 /*****************************************************************************/
    315 /*
    316  * Check for memory leaks. Not production quality code
    317  */
    318 int psMemCheckLeaks(
    319     int id0,    // don't list blocks with id < id0
    320     psMemBlock ***arr,   // pointer to array of pointers to
    321     // leaked blocks, or NULL
    322     FILE *fd)    // print list of leaks to fd (or NULL)
    323 {
    324     int nleak = 0;
    325 
    326     if (memBlocks == NULL)
    327     {  // nothing was allocated
    328         return 0;
    329     }
    330 
    331     for (int i = id0; i <= memid; i++)
    332     {
    333         if (memBlocks[i] != NULL) {
    334             if (memBlocks[i]->refCounter > 0) {
    335                 nleak++;
    336 
    337                 if (fd != NULL) {
    338                     if (nleak == 1) {
    339                         fprintf(fd, "   %20s:line ID\n", "file");
    340                     }
    341 
    342                     fprintf(fd, "   %20s:%-4d %ld\n",
    343                             memBlocks[i]->file, memBlocks[i]->lineno,
    344                             memBlocks[i]->id);
    345                 }
    346             }
    347         }
    348     }
    349 
    350     if (nleak == 0 || arr == NULL)
    351     {
    352         return nleak;
    353     }
    354 
    355     p_psFree(*arr,__FILE__, __LINE__);  // Don't generate a memory leak!
    356 
    357     *arr = p_psAlloc(nleak*sizeof(psMemBlock), __FILE__, __LINE__);
    358     for (int i = id0, j = 0; i < memid; i++)
    359     {
    360         if (memBlocks[i] != NULL) {
    361             if (memBlocks[i]->refCounter > 0) {
    362                 (*arr)[j++] = memBlocks[i];
    363                 if (j == nleak) { // found them all
    364                     break;
    365                 }
    366             }
    367         }
    368     }
     395    }
     396
     397    pthread_mutex_unlock(&memBlockListMutex);
    369398
    370399    return nleak;
     
    389418void *psMemIncrRefCounter(void *vptr) // increment and return refCounter
    390419{
    391     if (vptr == NULL)
    392     {
     420    if (vptr == NULL) {
    393421        return vptr;
    394422    }
     
    396424    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    397425
    398     if (checkMemBlock(ptr, __func__))
    399     {
     426    if (checkMemBlock(ptr, __func__)) {
    400427        memProblemCallback(ptr, __func__, __LINE__);
    401428    }
     
    408435void *psMemDecrRefCounter(void *vptr) // decrement and return refCounter
    409436{
    410     if (vptr == NULL)
    411     {
     437    if (vptr == NULL) {
    412438        return vptr;
    413439    }
     
    415441    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
    416442
    417     if (checkMemBlock(ptr, __func__))
    418     {
     443    if (checkMemBlock(ptr, __func__)) {
    419444        memProblemCallback(ptr, __func__, __LINE__);
    420445    }
  • trunk/psLib/src/sysUtils/psMemory.h

    r432 r451  
    1414 *  @author Robert Lupton, Princeton University
    1515 *
    16  *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
    17  *  @date $Date: 2004-04-16 02:18:57 $
     16 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
     17 *  @date $Date: 2004-04-19 20:14:04 $
    1818 *
    1919 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2525 *  aligned for all storage types.
    2626 */
    27 typedef struct
     27typedef struct psMemBlock
    2828{
    29     const void *startblock;             ///< initialised to p_psMEMMAGIC
     29    const void* startblock;             ///< initialised to p_psMEMMAGIC
     30        struct psMemBlock* previousBlock;   ///< previous block in allocation list
     31        struct psMemBlock* nextBlock;       ///< next block allocation list
    3032    const unsigned long id;             ///< a unique ID for this allocation
    31     const char *file;                   ///< set from __FILE__ in e.g. p_psAlloc
     33    const char* file;                   ///< set from __FILE__ in e.g. p_psAlloc
    3234    const int lineno;                   ///< set from __LINE__ in e.g. p_psAlloc
    33     int refCounter;                     ///< how many times pointer is referenced
    34     const void **endpost;               ///< initialised to p_psMEMMAGIC
    35     const void *endblock;               ///< initialised to p_psMEMMAGIC
     35    unsigned int refCounter;            ///< how many times pointer is referenced
     36    const void* endblock;               ///< initialised to p_psMEMMAGIC
    3637}
    3738psMemBlock;
     
    4344typedef long (*psMemFreeCallback)(const psMemBlock *ptr);
    4445
    45 /// prototype of a callback used in error conditions
     46/** prototype of a callback used in error conditions
     47 *
     48 *  This callback should never try to call psAlloc or psFree.
     49 *
     50 */
    4651typedef void (*psMemProblemCallback)(const psMemBlock *ptr, const char *file, int lineno);
    4752
Note: See TracChangeset for help on using the changeset viewer.