]> granicus.if.org Git - postgresql/commitdiff
Clean up MEMORY_CONTEXT_CHECKING code, and apply it more thoroughly. Also,
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 1 Dec 2000 05:16:45 +0000 (05:16 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 1 Dec 2000 05:16:45 +0000 (05:16 +0000)
apply Karel Zak's patch to recycle residual space in an exhausted allocation
block.  (Bet you thought I'd forgot about that, Karel?)

src/backend/utils/mmgr/aset.c
src/include/utils/memutils.h

index b5f552647eff486f3a04a97b5c591b7fb373653c..6a380061069063aa0baea9b9fb586be568b6a6a8 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.32 2000/11/16 05:51:02 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.33 2000/12/01 05:16:45 tgl Exp $
  *
  * NOTE:
  *     This is a new (Feb. 05, 1999) implementation of the allocation set
  *     when the caller is repeatedly repalloc()'ing a block bigger and bigger;
  *     the previous instances of the block were guaranteed to be wasted until
  *     AllocSetReset() under the old way.
+ *
+ *     About CLOBBER_FREED_MEMORY:
+ *
+ *     If this symbol is defined, all freed memory is overwritten with 0x7F's.
+ *     This is useful for catching places that reference already-freed memory.
+ *
+ *     About MEMORY_CONTEXT_CHECKING:
+ *
+ *     Since we usually round request sizes up to the next power of 2, there
+ *     is often some unused space immediately after a requested data area.
+ *     Thus, if someone makes the common error of writing past what they've
+ *     requested, the problem is likely to go unnoticed ... until the day when
+ *     there *isn't* any wasted space, perhaps because of different memory
+ *     alignment on a new platform, or some other effect.  To catch this sort
+ *     of problem, the MEMORY_CONTEXT_CHECKING option stores 0x7E just beyond
+ *     the requested space whenever the request is less than the actual chunk
+ *     size, and verifies that the byte is undamaged when the chunk is freed.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -38,9 +56,8 @@
 
 #include "utils/memutils.h"
 
-/* Define this to detail debug alloc information 
- */
-/*#define HAVE_ALLOCINFO       1*/
+/* Define this to detail debug alloc information */
+/* #define HAVE_ALLOCINFO */
 
 /*
  * AllocSetContext is defined in nodes/memnodes.h.
@@ -82,12 +99,13 @@ typedef struct AllocBlockData
 typedef struct AllocChunkData
 {
        /* aset is the owning aset if allocated, or the freelist link if free */
-       void    *aset;
+       void       *aset;
        /* size is always the size of the usable space in the chunk */
-       Size    size;
+       Size            size;
 #ifdef MEMORY_CONTEXT_CHECKING
-       Size    data_size;      
-#endif                 
+       /* when debugging memory usage, also store actual requested size */
+       Size            requested_size;
+#endif
 } AllocChunkData;
 
 /*
@@ -155,8 +173,6 @@ typedef struct AllocChunkData
                                        ((AllocChunk)(((char *)(ptr)) - ALLOC_CHUNKHDRSZ))
 #define AllocChunkGetPointer(chk)      \
                                        ((AllocPointer)(((char *)(chk)) + ALLOC_CHUNKHDRSZ))
-#define AllocPointerGetAset(ptr)       ((AllocSet)(AllocPointerGetChunk(ptr)->aset))
-#define AllocPointerGetSize(ptr)       (AllocPointerGetChunk(ptr)->size)
 
 /*
  * These functions implement the MemoryContext API for AllocSet contexts.
@@ -167,11 +183,9 @@ static void *AllocSetRealloc(MemoryContext context, void *pointer, Size size);
 static void AllocSetInit(MemoryContext context);
 static void AllocSetReset(MemoryContext context);
 static void AllocSetDelete(MemoryContext context);
-
 #ifdef MEMORY_CONTEXT_CHECKING
 static void AllocSetCheck(MemoryContext context);
 #endif
-
 static void AllocSetStats(MemoryContext context);
 
 /*
@@ -293,11 +307,6 @@ AllocSetContextCreate(MemoryContext parent,
                context->blocks = block;
                /* Mark block as not to be released at reset time */
                context->keeper = block;
-
-#ifdef MEMORY_CONTEXT_CHECKING
-               /* mark memory for memory leak searching */
-               memset(block->freeptr, 0x7F, blksize - ALLOC_BLOCKHDRSZ);
-#endif
        }
 
        return (MemoryContext) context;
@@ -342,6 +351,11 @@ AllocSetReset(MemoryContext context)
 
        AssertArg(AllocSetIsValid(set));
 
+#ifdef MEMORY_CONTEXT_CHECKING
+       /* Check for corruption and leaks before freeing */
+       AllocSetCheck(context);
+#endif
+
        while (block != NULL)
        {
                AllocBlock      next = block->next;
@@ -353,7 +367,7 @@ AllocSetReset(MemoryContext context)
 
 #ifdef CLOBBER_FREED_MEMORY
                        /* Wipe freed memory for debugging purposes */
-                       memset(datastart, 0x7F, ((char *) block->freeptr) - datastart);
+                       memset(datastart, 0x7F, block->freeptr - datastart);
 #endif
                        block->freeptr = datastart;
                        block->next = NULL;
@@ -363,7 +377,7 @@ AllocSetReset(MemoryContext context)
                        /* Normal case, release the block */
 #ifdef CLOBBER_FREED_MEMORY
                        /* Wipe freed memory for debugging purposes */
-                       memset(block, 0x7F, ((char *) block->freeptr) - ((char *) block));
+                       memset(block, 0x7F, block->freeptr - ((char *) block));
 #endif
                        free(block);
                }
@@ -392,13 +406,18 @@ AllocSetDelete(MemoryContext context)
 
        AssertArg(AllocSetIsValid(set));
 
+#ifdef MEMORY_CONTEXT_CHECKING
+       /* Check for corruption and leaks before freeing */
+       AllocSetCheck(context);
+#endif
+
        while (block != NULL)
        {
                AllocBlock      next = block->next;
 
 #ifdef CLOBBER_FREED_MEMORY
                /* Wipe freed memory for debugging purposes */
-               memset(block, 0x7F, ((char *) block->endptr) - ((char *) block));
+               memset(block, 0x7F, block->freeptr - ((char *) block));
 #endif
                free(block);
                block = next;
@@ -422,53 +441,47 @@ AllocSetAlloc(MemoryContext context, Size size)
        AllocBlock      block;
        AllocChunk      chunk;
        AllocChunk      priorfree = NULL;
-       int             fidx;
+       int                     fidx;
        Size            chunk_size;
        Size            blksize;
 
        AssertArg(AllocSetIsValid(set));
 
        /*
-        * Small size can be in free list 
+        * Lookup in the corresponding free list if there is a free chunk we
+        * could reuse
         */
-       if (size < ALLOC_BIGCHUNK_LIMIT)
+       fidx = AllocSetFreeIndex(size);
+       for (chunk = set->freelist[fidx]; chunk; chunk = (AllocChunk) chunk->aset)
        {
-               /*
-                * Lookup in the corresponding free list if there is a free chunk we
-                * could reuse
-                */
-               fidx = AllocSetFreeIndex(size);
-               for (chunk = set->freelist[fidx]; chunk; chunk = (AllocChunk) chunk->aset)
-               {
-                       if (chunk->size >= size)
-                               break;
-                       priorfree = chunk;
-               }
+               if (chunk->size >= size)
+                       break;
+               priorfree = chunk;
+       }
 
-               /*
-                * If one is found, remove it from the free list, make it again a
-                * member of the alloc set and return its data address.
-                */
-               if (chunk != NULL)
-               {
-                       if (priorfree == NULL)
-                               set->freelist[fidx] = (AllocChunk) chunk->aset;
-                       else
-                               priorfree->aset = chunk->aset;
-       
-                       chunk->aset = (void *) set;
+       /*
+        * If one is found, remove it from the free list, make it again a
+        * member of the alloc set and return its data address.
+        */
+       if (chunk != NULL)
+       {
+               if (priorfree == NULL)
+                       set->freelist[fidx] = (AllocChunk) chunk->aset;
+               else
+                       priorfree->aset = chunk->aset;
+
+               chunk->aset = (void *) set;
 
 #ifdef MEMORY_CONTEXT_CHECKING
-                       chunk->data_size = size;
+               chunk->requested_size = size;
+               /* set mark to catch clobber of "unused" space */
+               if (size < chunk->size)
+                       ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
 #endif
-                       AllocAllocInfo(set, chunk);
-                       return AllocChunkGetPointer(chunk);
-               }
-       } 
-       else
-               /* Big chunk
-                */
-               fidx = ALLOCSET_NUM_FREELISTS - 1;
+
+               AllocAllocInfo(set, chunk);
+               return AllocChunkGetPointer(chunk);
+       }
 
        /*
         * Choose the actual chunk size to allocate.
@@ -510,6 +523,12 @@ AllocSetAlloc(MemoryContext context, Size size)
                chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);
                chunk->aset = set;
                chunk->size = chunk_size;
+#ifdef MEMORY_CONTEXT_CHECKING
+               chunk->requested_size = size;
+               /* set mark to catch clobber of "unused" space */
+               if (size < chunk->size)
+                       ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
+#endif
 
                /*
                 * Try to stick the block underneath the active allocation block,
@@ -526,11 +545,6 @@ AllocSetAlloc(MemoryContext context, Size size)
                        set->blocks = block;
                }
                
-#ifdef MEMORY_CONTEXT_CHECKING
-               chunk->data_size = size;
-               /* mark memory for memory leak searching */
-               memset(AllocChunkGetPointer(chunk), 0x7F, chunk->size);         
-#endif
                AllocAllocInfo(set, chunk);
                return AllocChunkGetPointer(chunk);
        }
@@ -547,6 +561,47 @@ AllocSetAlloc(MemoryContext context, Size size)
                }
                else
                {
+                       /*
+                        * The existing active (top) block does not have enough room
+                        * for the requested allocation, but it might still have a
+                        * useful amount of space in it.  Once we push it down in the
+                        * block list, we'll never try to allocate more space from it.
+                        * So, before we do that, carve up its free space into chunks
+                        * that we can put on the set's freelists.
+                        */
+                       Size    availspace = set->blocks->endptr - set->blocks->freeptr;
+
+                       while (availspace >= ((1 << ALLOC_MINBITS) + ALLOC_CHUNKHDRSZ))
+                       {
+                               Size    availchunk = availspace - ALLOC_CHUNKHDRSZ;
+                               int             x_fidx = AllocSetFreeIndex(availchunk);
+
+                               /*
+                                * In most cases, we'll get back the index of the next larger
+                                * freelist than the one we need to put this chunk on.  The
+                                * exceptions are when availchunk is exactly a power of 2,
+                                * or is large enough that we're dealing with the last
+                                * (variable-chunk-size) freelist.  This test detects both:
+                                */
+                               if (availchunk < (1 << (x_fidx + ALLOC_MINBITS)))
+                               {
+                                       x_fidx--;       
+                                       Assert(x_fidx >= 0);
+                                       availchunk = (1 << (x_fidx + ALLOC_MINBITS));
+                               }
+
+                               chunk = (AllocChunk) (set->blocks->freeptr);
+                               chunk->size = availchunk;
+#ifdef MEMORY_CONTEXT_CHECKING
+                               chunk->requested_size = 0; /* mark it free */
+#endif
+                               chunk->aset = (void *) set->freelist[x_fidx];
+                               set->freelist[x_fidx] = chunk;
+
+                               set->blocks->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
+                               availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
+                       }
+
                        /* Get size of prior block */
                        blksize = set->blocks->endptr - ((char *) set->blocks);
 
@@ -586,12 +641,7 @@ AllocSetAlloc(MemoryContext context, Size size)
                block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
                block->endptr = ((char *) block) + blksize;
 
-#ifdef MEMORY_CONTEXT_CHECKING
-               /* mark memory for memory leak searching */
-               memset(block->freeptr, 0x7F, blksize - ALLOC_BLOCKHDRSZ);
-#endif
                block->next = set->blocks;
-
                set->blocks = block;
        }
 
@@ -601,10 +651,13 @@ AllocSetAlloc(MemoryContext context, Size size)
        chunk = (AllocChunk) (block->freeptr);
        chunk->aset = (void *) set;
        chunk->size = chunk_size;
-       
 #ifdef MEMORY_CONTEXT_CHECKING
-       chunk->data_size = size;
+       chunk->requested_size = size;
+       /* set mark to catch clobber of "unused" space */
+       if (size < chunk->size)
+               ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
 #endif 
+
        block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
        Assert(block->freeptr <= block->endptr);
 
@@ -622,15 +675,16 @@ AllocSetFree(MemoryContext context, void *pointer)
        AllocSet        set = (AllocSet) context;
        AllocChunk      chunk = AllocPointerGetChunk(pointer);
 
-#if defined(CLOBBER_FREED_MEMORY) || defined(MEMORY_CONTEXT_CHECKING)
-       /* Wipe freed memory for debugging purposes or for memory leak 
-        * searching (in freelist[] must be mark memory
-        */
-       memset(pointer, 0x7F, chunk->size);
-#endif
-
        AllocFreeInfo(set, chunk);
 
+#ifdef MEMORY_CONTEXT_CHECKING
+       /* Test for someone scribbling on unused space in chunk */
+       if (chunk->requested_size < chunk->size)
+               if (((char *) pointer)[chunk->requested_size] != 0x7E)
+                       elog(ERROR, "AllocSetFree: detected write past chunk end in %p",
+                                chunk);
+#endif 
+
        if (chunk->size >= ALLOC_BIGCHUNK_LIMIT)
        {
                /*
@@ -659,7 +713,7 @@ AllocSetFree(MemoryContext context, void *pointer)
                        prevblock->next = block->next;
 #ifdef CLOBBER_FREED_MEMORY
                /* Wipe freed memory for debugging purposes */
-               memset(block, 0x7F, ((char *) block->endptr) - ((char *) block));
+               memset(block, 0x7F, block->freeptr - ((char *) block));
 #endif
                free(block);
        }
@@ -670,8 +724,14 @@ AllocSetFree(MemoryContext context, void *pointer)
 
                chunk->aset = (void *) set->freelist[fidx];
 
+#ifdef CLOBBER_FREED_MEMORY
+               /* Wipe freed memory for debugging purposes */
+               memset(pointer, 0x7F, chunk->size);
+#endif
+
 #ifdef MEMORY_CONTEXT_CHECKING
-               chunk->data_size = 0;
+               /* Reset requested_size to 0 in chunks that are on freelist */
+               chunk->requested_size = 0;
 #endif         
                set->freelist[fidx] = chunk;
        }
@@ -687,23 +747,29 @@ static void *
 AllocSetRealloc(MemoryContext context, void *pointer, Size size)
 {
        AllocSet        set = (AllocSet) context;
-       Size            oldsize;
+       AllocChunk      chunk = AllocPointerGetChunk(pointer);
+       Size            oldsize = chunk->size;
+
+#ifdef MEMORY_CONTEXT_CHECKING         
+       /* Test for someone scribbling on unused space in chunk */
+       if (chunk->requested_size < oldsize)
+               if (((char *) pointer)[chunk->requested_size] != 0x7E)
+                       elog(ERROR, "AllocSetRealloc: detected write past chunk end in %p",
+                                chunk);
+#endif
 
        /*
         * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
         * allocated area already is >= the new size.  (In particular, we
         * always fall out here if the requested size is a decrease.)
         */
-       oldsize = AllocPointerGetSize(pointer);
        if (oldsize >= size)
        {
 #ifdef MEMORY_CONTEXT_CHECKING         
-               AllocChunk      chunk = AllocPointerGetChunk(pointer);
-
-               /* mark memory for memory leak searching */
-               memset(((char *) chunk) + (ALLOC_CHUNKHDRSZ + size), 
-                               0x7F, chunk->size - size);
-               chunk->data_size = size;
+               chunk->requested_size = size;
+               /* set mark to catch clobber of "unused" space */
+               if (size < chunk->size)
+                       ((char *) pointer)[size] = 0x7E;
 #endif
                return pointer;
        }
@@ -717,13 +783,10 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
                 * block and use realloc() to make it bigger with minimum space
                 * wastage.
                 */
-               AllocChunk      chunk = AllocPointerGetChunk(pointer);
                AllocBlock      block = set->blocks;
                AllocBlock      prevblock = NULL;
+               Size            chksize;
                Size            blksize;
-#ifdef MEMORY_CONTEXT_CHECKING         
-               Size            data_size = size;
-#endif
 
                while (block != NULL)
                {
@@ -739,8 +802,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
                           (chunk->size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ));
 
                /* Do the realloc */
-               size = MAXALIGN(size);
-               blksize = size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+               chksize = MAXALIGN(size);
+               blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
                block = (AllocBlock) realloc(block, blksize);
                if (block == NULL)
                        elog(ERROR, "Memory exhausted in AllocSetReAlloc()");
@@ -752,14 +815,15 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
                        set->blocks = block;
                else
                        prevblock->next = block;
-               chunk->size = size;
+               chunk->size = chksize;
                
 #ifdef MEMORY_CONTEXT_CHECKING
-               /* mark memory for memory leak searching */
-               memset(((char *) chunk) + (ALLOC_CHUNKHDRSZ + data_size), 
-                               0x7F, size - data_size);
-               chunk->data_size = data_size;
+               chunk->requested_size = size;
+               /* set mark to catch clobber of "unused" space */
+               if (size < chunk->size)
+                       ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
 #endif
+
                return AllocChunkGetPointer(chunk);
        }
        else
@@ -817,25 +881,22 @@ AllocSetStats(MemoryContext context)
 }
 
 
+#ifdef MEMORY_CONTEXT_CHECKING
+
 /* 
  * AllocSetCheck
- *             Walk on chunks and check consistence of memory. 
+ *             Walk through chunks and check consistency of memory.
  */
-#ifdef MEMORY_CONTEXT_CHECKING
-
 static void 
 AllocSetCheck(MemoryContext context)
 {
        AllocSet        set = (AllocSet) context;       
-       AllocBlock      block = NULL;
-       AllocChunk      chunk = NULL;
        char            *name = set->header.name;
+       AllocBlock      block;
 
        for (block = set->blocks; block != NULL; block = block->next)
        {       
                char    *bpoz = ((char *) block) + ALLOC_BLOCKHDRSZ;
-       /*      long    blk_size = block->endptr - ((char *) block);*/
-               long    blk_free = block->endptr - block->freeptr; 
                long    blk_used = block->freeptr - bpoz;
                long    blk_data = 0;
                long    nchunks  = 0;
@@ -845,96 +906,67 @@ AllocSetCheck(MemoryContext context)
                 */
                if (!blk_used)
                {
-                       if (set->keeper == block)
-                               continue;
-                       else    
-                               elog(ERROR, "AllocSetCheck(): %s: empty block %p", 
-                                               name, block);
+                       if (set->keeper != block)
+                               elog(NOTICE, "AllocSetCheck(): %s: empty block %p", 
+                                        name, block);
                }       
                
                /*
                 * Chunk walker
                 */     
-               do {
-                       Size    chsize,
-                               dsize;
-                       char    *chdata_end,
-                               *chend;
-                               
-                       chunk = (AllocChunk) bpoz;
-                       
-                       chsize = chunk->size;           /* align chunk size */
-                       dsize = chunk->data_size;       /* real data */
+               while (bpoz < block->freeptr)
+               {
+                       AllocChunk      chunk = (AllocChunk) bpoz;
+                       Size            chsize,
+                                               dsize;
+                       char       *chdata_end;
                        
+                       chsize = chunk->size; /* aligned chunk size */
+                       dsize = chunk->requested_size;  /* real data */
                        chdata_end = ((char *) chunk) + (ALLOC_CHUNKHDRSZ + dsize);
-                       chend = ((char *) chunk) + (ALLOC_CHUNKHDRSZ + chsize);
                        
-                       if (!dsize && chsize < dsize)
-                               elog(ERROR, "AllocSetCheck(): %s: internal error for chunk %p in block %p",
-                                               name, chunk, block);                    
                        /*
                         * Check chunk size
                         */
+                       if (dsize > chsize)
+                               elog(ERROR, "AllocSetCheck(): %s: req size > alloc size for chunk %p in block %p",
+                                        name, chunk, block);                   
                        if (chsize < (1 << ALLOC_MINBITS))
-                               elog(ERROR, "AllocSetCheck(): %s: bad size '%lu' for chunk %p in block %p",
-                                               name, (unsigned long)chsize, chunk, block);
+                               elog(ERROR, "AllocSetCheck(): %s: bad size %lu for chunk %p in block %p",
+                                        name, (unsigned long) chsize, chunk, block);
                                                
-                       /* single-chunk block */
+                       /* single-chunk block? */
                        if (chsize >= ALLOC_BIGCHUNK_LIMIT &&
                            chsize + ALLOC_CHUNKHDRSZ != blk_used)
-                               elog(ERROR, "AllocSetCheck(): %s: bad singel-chunk %p in block %p",
-                                               name, chunk, block);
-                                               
-                       /*
-                        * Check in-chunk leak
-                        */             
-                       if (dsize < chsize && *chdata_end != 0x7F)
-                       {
-                               fprintf(stderr, "\n--- Leak %p ---\n", chdata_end);
-                               fprintf(stderr, "Chunk dump size: %ld (chunk-header %ld + chunk-size: %lu), data must be: %lu\n--- dump begin ---\n", 
-                                       chsize + ALLOC_CHUNKHDRSZ, 
-                                       ALLOC_CHUNKHDRSZ, (unsigned long)chsize, (unsigned long)dsize);
-                                       
-                               fwrite((void *) chunk, chsize+ALLOC_CHUNKHDRSZ, sizeof(char), stderr);
-                               fputs("\n--- dump end ---\n", stderr);
-                               
-                               elog(ERROR, "AllocSetCheck(): %s: found in-chunk memory leak (block %p; chunk %p; leak at %p",
-                                               name, block, chunk, chdata_end);
-                       }
-                       
+                               elog(ERROR, "AllocSetCheck(): %s: bad single-chunk %p in block %p",
+                                        name, chunk, block);
+
                        /*
-                        * Check block-freeptr leak 
+                        * If chunk is allocated, check for correct aset pointer.
+                        * (If it's free, the aset is the freelist pointer, which we
+                        * can't check as easily...)
                         */
-                       if (chend == block->freeptr && blk_free && 
-                                                       *chdata_end != 0x7F) {
-                               
-                               fprintf(stderr, "\n--- Leak %p ---\n", chdata_end);
-                               fprintf(stderr, "Dump size: %ld (chunk-header %ld + chunk-size: %lu + block-freespace: %ld), data must be: %lu\n--- dump begin ---\n", 
-                                       chsize + ALLOC_CHUNKHDRSZ + blk_free, 
-                                       ALLOC_CHUNKHDRSZ, (unsigned long)chsize, blk_free, (unsigned long)dsize);
-                                       
-                               fwrite((void *) chunk, chsize+ALLOC_CHUNKHDRSZ+blk_free, sizeof(char), stderr);
-                               fputs("\n--- dump end ---\n", stderr);
-                               
-                               elog(ERROR, "AllocSetCheck(): %s: found block-freeptr memory leak (block %p; chunk %p; leak at %p",
-                                               name, block, chunk, chdata_end);
-                       }                       
+                       if (dsize > 0 && chunk->aset != (void *) set)
+                               elog(ERROR, "AllocSetCheck(): %s: bogus aset link in block %p, chunk %p",
+                                        name, block, chunk);
+
+                       /*
+                        * Check for overwrite of "unallocated" space in chunk
+                        */             
+                       if (dsize > 0 && dsize < chsize && *chdata_end != 0x7E)
+                               elog(ERROR, "AllocSetCheck(): %s: detected write past chunk end in block %p, chunk %p",
+                                        name, block, chunk);
                        
                        blk_data += chsize;
                        nchunks++;
                        
-                       if (chend < block->freeptr)
-                               bpoz += ALLOC_CHUNKHDRSZ + chsize;
-                       else
-                               break;
+                       bpoz += ALLOC_CHUNKHDRSZ + chsize;
+               }
 
-               } while(block->freeptr > bpoz); /* chunk walker */              
-       
-               
                if ((blk_data + (nchunks * ALLOC_CHUNKHDRSZ)) != blk_used)
-
-                       elog(ERROR, "AllocSetCheck(): %s: found non-consistent memory block %p",
-                                       name, block);
+                       elog(ERROR, "AllocSetCheck(): %s: found inconsistent memory block %p",
+                                name, block);
        }
 }
-#endif
+
+#endif /* MEMORY_CONTEXT_CHECKING */
index be322cbccc3dc6c7c2105ce84c2fbe31daef3468..79e41b2df1332e38b95373fa17badf84a4dce5f1 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: memutils.h,v 1.37 2000/07/11 14:30:37 momjian Exp $
+ * $Id: memutils.h,v 1.38 2000/12/01 05:16:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 typedef struct StandardChunkHeader
 {
-       MemoryContext context;                  /* owning context */
-       Size size;                                              /* size of data space allocated in chunk */
+       MemoryContext   context;        /* owning context */
+       Size            size;                   /* size of data space allocated in chunk */
 #ifdef MEMORY_CONTEXT_CHECKING
-       Size data_size;                         /* real data size  (without align) */
+       /* when debugging memory usage, also store actual requested size */
+       Size            requested_size;
 #endif
 } StandardChunkHeader;