⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap03.htm

📁 C++编程思想第二版第二卷
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<font color=#009900>// Comment out the following to send all the</font>
<font color=#009900>// information to the trace file:</font>
#define memtrace stdout

<font color=#0000ff>const</font> <font color=#0000ff>unsigned</font> <font color=#0000ff>long</font> _pool_sz = 50000L;
<font color=#0000ff>static</font> <font color=#0000ff>unsigned</font> <font color=#0000ff>char</font> _memory_pool[_pool_sz];
<font color=#0000ff>static</font> <font color=#0000ff>unsigned</font> <font color=#0000ff>char</font>* _pool_ptr = _memory_pool;

<font color=#0000ff>void</font>* getmem(size_t sz) {
  <font color=#0000ff>if</font>(_memory_pool + _pool_sz - _pool_ptr &lt; sz) {
    fprintf(stderr,
           <font color=#004488>"Out of memory. Use bigger model\n"</font>);
    exit(1);
  }
  <font color=#0000ff>void</font>* p = _pool_ptr;
  _pool_ptr += sz;
  <font color=#0000ff>return</font> p;
}

<font color=#009900>// Holds information about allocated pointers:</font>
<font color=#0000ff>class</font> MemBag { 
<font color=#0000ff>public</font>:
  <font color=#0000ff>enum</font> type { Malloc, New };
<font color=#0000ff>private</font>:
  <font color=#0000ff>char</font>* typestr(type t) {
    <font color=#0000ff>switch</font>(t) {
      <font color=#0000ff>case</font> Malloc: <font color=#0000ff>return</font> <font color=#004488>"malloc"</font>;
      <font color=#0000ff>case</font> New: <font color=#0000ff>return</font> <font color=#004488>"new"</font>;
      <font color=#0000ff>default</font>: <font color=#0000ff>return</font> <font color=#004488>"?unknown?"</font>;
    }
  }
  <font color=#0000ff>struct</font> M {
    <font color=#0000ff>void</font>* mp;  <font color=#009900>// Memory pointer</font>
    type t;     <font color=#009900>// Allocation type</font>
    <font color=#0000ff>char</font>* file; <font color=#009900>// File name where allocated</font>
    <font color=#0000ff>int</font> line;  <font color=#009900>// Line number where allocated</font>
    M(<font color=#0000ff>void</font>* v, type tt, <font color=#0000ff>char</font>* f, <font color=#0000ff>int</font> l)
      : mp(v), t(tt), file(f), line(l) {}
  }* v;
  <font color=#0000ff>int</font> sz, next;
  <font color=#0000ff>enum</font> { increment = 50 };
<font color=#0000ff>public</font>:
  MemBag() : v(0), sz(0), next(0) {}
  <font color=#0000ff>void</font>* add(<font color=#0000ff>void</font>* p, type tt = Malloc,
            <font color=#0000ff>char</font>* s = <font color=#004488>"library"</font>, <font color=#0000ff>int</font> l = 0) {
    <font color=#0000ff>if</font>(next &gt;= sz) {
      sz += increment;
      <font color=#009900>// This memory is never freed, so it</font>
      <font color=#009900>// doesn't "get involved" in the test:</font>
      <font color=#0000ff>const</font> <font color=#0000ff>int</font> memsize = sz * <font color=#0000ff>sizeof</font>(M);
      <font color=#009900>// Equivalent of realloc, no registration:</font>
      <font color=#0000ff>void</font>* p = getmem(memsize);
      <font color=#0000ff>if</font>(v) memmove(p, v, memsize);
      v = (M*)p;
      memset(&amp;v[next], 0,
             increment * <font color=#0000ff>sizeof</font>(M));
    }
    v[next++] = M(p, tt, s, l);
    <font color=#0000ff>return</font> p;
  }
  <font color=#009900>// Print information about allocation:</font>
  <font color=#0000ff>void</font> allocation(<font color=#0000ff>int</font> i) {
    fprintf(memtrace, <font color=#004488>"pointer %p"</font>
      <font color=#004488>" allocated with %s"</font>,
      v[i].mp, typestr(v[i].t));
    <font color=#0000ff>if</font>(v[i].t == New)
      fprintf(memtrace, <font color=#004488>" at %s: %d"</font>,
        v[i].file, v[i].line);
    fprintf(memtrace, <font color=#004488>"\n"</font>);
  }
  <font color=#0000ff>void</font> validate(<font color=#0000ff>void</font>* p, type T = Malloc) {
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; next; i++)
      <font color=#0000ff>if</font>(v[i].mp == p) {
        <font color=#0000ff>if</font>(v[i].t != T) {
          allocation(i);
          fprintf(memtrace,
          <font color=#004488>"\t was released as if it were "</font>
          <font color=#004488>"allocated with %s \n"</font>, typestr(T));
        }
        v[i].mp = 0;  <font color=#009900>// Erase it</font>
        <font color=#0000ff>return</font>;
      }
    fprintf(memtrace,
    <font color=#004488>"pointer not in memory list: %p\n"</font>, p);
  }
  ~MemBag() {
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; next; i++)
      <font color=#0000ff>if</font>(v[i].mp != 0) {
        fprintf(memtrace,
        <font color=#004488>"pointer not released: "</font>);
        allocation(i);
      }
  }
};
<font color=#0000ff>extern</font> MemBag MEMBAG_;

<font color=#0000ff>void</font>* malloc(size_t sz) {
  <font color=#0000ff>void</font>* p = getmem(sz);
  <font color=#0000ff>return</font> MEMBAG_.add(p, MemBag::Malloc);
}

<font color=#0000ff>void</font>* calloc(size_t num_elems, size_t elem_sz) {
  <font color=#0000ff>void</font>* p = getmem(num_elems * elem_sz);
  memset(p, 0, num_elems * elem_sz);
  <font color=#0000ff>return</font> MEMBAG_.add(p, MemBag::Malloc);
}  

<font color=#0000ff>void</font>* realloc(<font color=#0000ff>void</font>* block, size_t sz) {
  <font color=#0000ff>void</font>* p = getmem(sz);
  <font color=#0000ff>if</font>(block) memmove(p, block, sz);
  <font color=#0000ff>return</font> MEMBAG_.add(p, MemBag::Malloc);
}

<font color=#0000ff>void</font> free(<font color=#0000ff>void</font>* v) { 
  MEMBAG_.validate(v, MemBag::Malloc);
}

<font color=#0000ff>void</font>* <font color=#0000ff>operator</font> <font color=#0000ff>new</font>(size_t sz) {
  <font color=#0000ff>void</font>* p = getmem(sz);
  <font color=#0000ff>return</font> MEMBAG_.add(p, MemBag::New);
}

<font color=#0000ff>void</font>*
<font color=#0000ff>operator</font> <font color=#0000ff>new</font>(size_t sz, <font color=#0000ff>char</font>* file, <font color=#0000ff>int</font> line) {
  <font color=#0000ff>void</font>* p = getmem(sz);
  <font color=#0000ff>return</font> MEMBAG_.add(p, MemBag::New, file, line);
}

<font color=#0000ff>void</font> <font color=#0000ff>operator</font> <font color=#0000ff>delete</font>(<font color=#0000ff>void</font>* v) {
  MEMBAG_.validate(v, MemBag::New);
}

MemBag MEMBAG_;
<font color=#009900>// Placed here so the constructor is called</font>
<font color=#009900>// AFTER that of MEMBAG_ :</font>
#ifdef memtrace
#undef memtrace
#endif
OFile memtrace(<font color=#004488>"memtrace.out"</font>);
<font color=#009900>// Causes 1 "pointer not in memory list" message</font>
<font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>OFile</B> is a simple wrapper around a
<B>FILE*</B>; the constructor opens the file and the destructor closes it. The
<B>operator FILE*(&#160;)</B> allows you to simply use the <B>OFile</B> object
anyplace you would ordinarily use a <B>FILE*</B> (in the <B>fprintf(&#160;)</B>
statements in this example). The <B>#define</B> that follows simply sends
everything to standard output, but if you need to put it in a trace file you
simply comment out that line.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Memory is allocated from an array called
<B>_memory_pool</B>. The <B>_pool_ptr</B> is moved forward every time storage is
allocated. For simplicity, the storage is never reclaimed, and
<B>realloc(&#160;)</B> doesn&#8217;t try to resize the storage in the same
place.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">All the storage allocation functions call
<B>getmem(&#160;)</B> which ensures there is enough space left and moves the
<B>_pool_ptr</B> to allocate your storage. Then they store the pointer in a
special container of class <B>MemBag</B> called <B>MEMBAG_</B>, along with
pertinent information (notice the two versions of <B>operator new</B>; one which
just stores the pointer and the other which stores the file and line number).
The <B>MemBag</B> class is the heart of the system.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You will see many similarities to
<B>xbag</B> in <B>MemBag</B>. A distinct difference is <B>realloc(&#160;)</B> is
replaced by a call to <B>getmem(&#160;)</B> and <B>memmove(&#160;)</B>, so that
storage allocated for the <B>MemBag</B> is not registered. In addition, the
<B>type</B> <B>enum</B> allows you to store the way the memory was allocated;
the <B>typestr(&#160;)</B> function takes a type and produces a string for use
with printing.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The nested <B>struct M</B> holds the
pointer, the type, a pointer to the file name (which is assumed to be statically
allocated) and the line where the allocation occurred. <B>v</B> is a pointer to
an array of <B>M</B> objects &#8211; this is the array which is dynamically
sized.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>allocation(&#160;)</B> function
prints out a different message depending on whether the storage was allocated
with <B>new</B> (where it has line and file information) or
<B>malloc(&#160;)</B> (where it doesn&#8217;t). This function is used inside
<B>validate(&#160;)</B>, which is called by <B>free(&#160;)</B> and
<B>delete(&#160;)</B> to ensure everything is OK, and in the destructor, to
ensure the pointer was cleaned up (note that in <B>validate(&#160;)</B> the
pointer value <B>v[i].mp</B> is set to zero, to indicate it has been cleaned
up).</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The following is a simple test using the
memcheck facility. The <B>MemCheck.obj</B> file must be linked in for it to
work:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C03:MemTest.cpp</font>
<font color=#009900>//{L} MemCheck</font>
<font color=#009900>//{-msc}</font>
<font color=#009900>// Test of MemCheck system</font>
#include <font color=#004488>"MemCheck.h"</font>

<font color=#0000ff>int</font> main() {
  <font color=#0000ff>void</font>* v = std::malloc(100);
  <font color=#0000ff>delete</font> v;
  <font color=#0000ff>int</font>* x = <font color=#0000ff>new</font> <font color=#0000ff>int</font>;
  std::free(x);
  <font color=#0000ff>new</font> <font color=#0000ff>double</font>;
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The trace file created in
<B>MemCheck.cpp</B> causes the generation of one "pointer not in memory list"
message, apparently from the creation of the file pointer on the heap. [[ This
may not still be true &#8211; test it
]]</FONT><A NAME="_Toc519041919"></A><BR></P></DIV>
<A NAME="Heading78"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
The canonical object &amp; singly-rooted
hierarchies<A NAME="_Toc519041920"></A></H2></FONT>
<A NAME="Heading79"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
An extended canonical form</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Including a set of methods (such as
trace/print/dump) in your library&#8217;s base class to enable easy
debugging.</FONT><A NAME="_Toc519041921"></A><BR></P></DIV>
<A NAME="Heading80"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Exercises</H2></FONT>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Create a heap compactor
for all dynamic memory in a particular program. This will require that you
control how objects are dynamically created and used (do you overload
<B>operator new</B> or does that approach work?). The typical heap-compaction
scheme requires that all pointers are doubly-indirected (that is, pointers to
pointers) so the &#8220;middle tier&#8221; pointer can be manipulated during
compaction. Consider overloading <B>operator-&gt;</B> to accomplish this, since
that operator has special behavior which will probably benefit your
heap-compaction scheme. Write a program to test your heap-compaction
scheme.</FONT></OL>
<DIV ALIGN="CENTER">
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
     [ <a href="Chap02.htm">Previous Chapter</a> ] 
    
    [ <a href="SimpCont.htm">Short TOC</a> ] 
    [ <a href="Contents.htm">Table of Contents</a> ] 
  
        [ <a href="DocIdx.htm">Index</a> ]
        
     [ <a href="Part2.htm">Next Chapter</a> ] 
    </FONT>
    <BR>
 Last Update:09/26/2001</P></DIV>

</BODY>

</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -