home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / MemCheck.C < prev    next >
C/C++ Source or Header  |  1998-09-21  |  7KB  |  300 lines

  1. // $Id: MemCheck.C,v 1.11 1998/09/21 19:12:56 zeller Exp $ -*- C++ -*-
  2. // Memory checker
  3.  
  4. // Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of the ICE Library.
  8. // 
  9. // The ICE Library is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU Library General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // The ICE Library is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU Library General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU Library General Public
  20. // License along with the ICE Library -- see the file COPYING.LIB.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // ICE is the incremental configuration environment.
  25. // For details, see the ICE World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ice/',
  27. // or send a mail to the ICE developers <ice@ips.cs.tu-bs.de>.
  28.  
  29. char MemCheck_rcsid[] =
  30.     "$Id: MemCheck.C,v 1.11 1998/09/21 19:12:56 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "MemCheck.h"
  37. #include "config.h"
  38.  
  39. #include <stdlib.h>
  40.  
  41. #if !HAVE_MALLOC_DECL
  42. extern "C" void *malloc(size_t size);
  43. #endif
  44.  
  45.  
  46. // Data
  47.  
  48. // Debugging flags
  49. int MemCheck::log           = 0;
  50. int MemCheck::wipeout_free  = 1;
  51.  
  52. MemCheckHeader MemCheck::freebase;
  53. MemCheckHeader MemCheck::allocbase;
  54.  
  55. MemCheckHeader *MemCheck::freep;  // Start of free list
  56. MemCheckHeader *MemCheck::allocp; // Start of alloc list
  57.  
  58. unsigned MemCheck::tics;    // Next available ID
  59.  
  60. unsigned MemCheck::freeBytes;    // Bytes in free list
  61. unsigned MemCheck::allocBytes;    // Bytes in alloc list
  62.  
  63. // Validate a header pointer
  64. inline void MemCheck::validate(MemCheckHeader *p, char *src)
  65. {
  66.     if (p->s.magic != MAGIC)
  67.     {
  68.     cerr << src << ": memory corrupted at " << (void *)p << "\n";
  69.     abort();
  70.     }
  71. }
  72.  
  73. // Allocate a block with size nbytes -- a la K&R
  74. void *MemCheck::alloc(unsigned nbytes)
  75. {
  76.     init();
  77.  
  78.     unsigned nunits =
  79.     (nbytes + sizeof(MemCheckHeader) - 1) / sizeof(MemCheckHeader) + 1;
  80.  
  81.     MemCheckHeader *prevp = freep;
  82.     validate(freep, "alloc");
  83.     for (MemCheckHeader *p = freep->s.ptr; ; prevp = p, p = p->s.ptr)
  84.     {
  85.     validate(p, "alloc");
  86.     
  87.     if (p->s.size >= nunits)
  88.     {
  89.         // big enough
  90.         if (p->s.size == nunits)
  91.         {
  92.         // suits fine
  93.         prevp->s.ptr = p->s.ptr;
  94.         }
  95.         else
  96.         {
  97.         // allocate from end of list
  98.  
  99.         p->s.size -= nunits;
  100.         p += p->s.size;
  101.         p->s.size = nunits;
  102.         }
  103.  
  104.         // Insert debugging info
  105.         p->s.magic     = MAGIC;
  106.         p->s.requested = nbytes;
  107.         p->s.tic       = tics++;
  108.         
  109.         // insert in alloc list
  110.         p->s.ptr = allocp->s.ptr;
  111.         allocp->s.ptr = p;
  112.         allocp = p;
  113.  
  114.         // sum up
  115.         allocBytes += nbytes;
  116.         freeBytes  -= nbytes;
  117.  
  118.         // update free list
  119.         freep = prevp;
  120.  
  121.         // return new block
  122.         void *ret = (void *)(p + 1);
  123.  
  124.         if (log)
  125.         clog << "alloc: " << nbytes << " bytes "
  126.              << "in block " << p->s.tic << " at " << ret << "\n";
  127.         
  128.         return ret;
  129.     }
  130.  
  131.     if (p == freep)
  132.     {
  133.         // we traversed the whole list: allocate more core
  134.         if ((p = morecore(nunits)) == 0)
  135.         return 0;
  136.     }
  137.     }
  138. }
  139.  
  140. // Return more core memory -- using malloc()
  141. MemCheckHeader *MemCheck::morecore(unsigned nunits)
  142. {
  143.     const unsigned NALLOC = 1024;
  144.     
  145.     if (nunits < NALLOC)
  146.     nunits = NALLOC;
  147.  
  148.     unsigned nbytes = nunits * sizeof(MemCheckHeader);
  149.  
  150.     void *cp = ::malloc(nbytes);
  151.  
  152.     if (cp == 0)
  153.     return 0;
  154.  
  155.     freeBytes += nbytes;
  156.  
  157.     MemCheckHeader *up = (MemCheckHeader *)cp;
  158.  
  159.     // make a single block and "free" it
  160.     up->s.size  = nunits;
  161.     up->s.magic = MAGIC;
  162.     _free(up);
  163.     
  164.     return freep;
  165. }
  166.  
  167. // Free a block previously returned by alloc -- a la K&R
  168. void MemCheck::free(void *ap)
  169. {
  170.     init();
  171.  
  172.     MemCheckHeader *bp = (MemCheckHeader *)ap - 1;
  173.  
  174.     validate(bp, "free");
  175.  
  176.     if (log)
  177.     clog << "free:  " << bp->s.requested << " bytes "
  178.          << "in block " << bp->s.tic << " at " << ap << "\n";
  179.  
  180.     if (wipeout_free)
  181.     {
  182.     // Wipe out memory
  183.     char *sweep = (char *)ap;
  184.     for (unsigned i = 0; i < bp->s.requested; i++)
  185.         *sweep++ = WIPEOUT;
  186.     }
  187.  
  188.     // Delete from alloc list
  189.     MemCheckHeader *prevp = allocp;
  190.     validate(allocp, "free");
  191.     
  192.     for (MemCheckHeader *p = allocp->s.ptr; ; prevp = p, p = p->s.ptr)
  193.     {
  194.     validate(p, "free");
  195.     
  196.     if (p == bp)
  197.     {
  198.         prevp->s.ptr = p->s.ptr;
  199.         allocp = prevp;
  200.         break;
  201.     }
  202.     
  203.     if (p == allocp)
  204.     {
  205.         // We traversed the whole list without finding the block
  206.         cerr << "free: cannot find block at " << ap << "\n";
  207.         abort();
  208.     }
  209.     }
  210.     
  211.     // Sum up
  212.     allocBytes -= bp->s.requested;
  213.     freeBytes  += bp->s.requested;
  214.  
  215.     // Insert in free list
  216.     _free(bp);
  217.  
  218. }
  219.  
  220. // Insert a block in free list -- a la K&R
  221. void MemCheck::_free(MemCheckHeader *bp)
  222. {
  223.     // Search neighbouring blocks in free list
  224.     MemCheckHeader *p;
  225.     for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
  226.     {
  227.     validate(p, "free");
  228.     
  229.     if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
  230.         break;
  231.     }
  232.  
  233.     if (bp + bp->s.size == p->s.ptr)
  234.     {
  235.     // Merge with right neighbour
  236.     bp->s.size += p->s.ptr->s.size;
  237.     bp->s.ptr = p->s.ptr->s.ptr;
  238.     }
  239.     else
  240.     bp->s.ptr = p->s.ptr;
  241.  
  242.     if (p + p->s.size == bp)
  243.     {
  244.     // Merge with left neighbour
  245.     p->s.size += bp->s.size;
  246.     p->s.ptr = bp->s.ptr;
  247.     }
  248.     else
  249.     p->s.ptr = bp;
  250.  
  251.     freep = p;
  252. }
  253.  
  254. // Issue an allocation map -- using the alloc list
  255. void MemCheck::map(ostream& os, unsigned start, char *prefix)
  256. {
  257.     init();
  258.  
  259.     unsigned found = 0;
  260.  
  261.     for (MemCheckHeader *p = allocp->s.ptr; ; p = p->s.ptr)
  262.     {
  263.     validate(p, "map");
  264.     
  265.     if (p->s.tic > 0 && p->s.tic >= start)
  266.     {
  267.         if (prefix[0] != '\0')
  268.         os << prefix << ": ";
  269.         os << p->s.requested << " bytes in block " << p->s.tic
  270.            << " at " << (void *)(p + 1) << "\n";
  271.         found++;
  272.     }
  273.         
  274.     if (p == allocp)
  275.         break;
  276.     }
  277.  
  278.     if (found)
  279.     {
  280.     if (prefix[0] != '\0')
  281.         os << prefix << ": ";
  282.     os << allocBytes << "/" << allocBytes + freeBytes << " bytes in use\n";
  283.     }
  284. }
  285.  
  286. // Validate
  287. int MemCheck::OK()
  288. {
  289.     init();
  290.  
  291.     for (MemCheckHeader *p = allocp->s.ptr; ; p = p->s.ptr)
  292.     {
  293.     validate(p, "OK");
  294.     if (p == allocp)
  295.         break;
  296.     }
  297.  
  298.     return 1;
  299. }
  300.