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

📄 chap03.htm

📁 This is the second part of that lab manual to teach you how to make real-time programme and how to d
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:C:\TEMP\TicV2\html\TicV2.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:09/26/2001
Translation Time:08:32:21
Translation Platform:Win32
Number of Output files:19
This File:C:\TEMP\TicV2\html\Chap03.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>3: Debugging Techniques</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
    [ <a href="README.txt">Viewing Hints</a> ]
    [ <a href="RevisionHistory.htm">Revision History</a> ]
    [ <a href="http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html">Book Home Page</a> ]
    [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/Services">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  Thinking in C++, 2nd edition, Volume 2<br>
  <small>Revision 4.0</small></FONT></H2>
  <H3><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  by Bruce Eckel &amp; Chuck Allison<br>&copy;2001 MindView, Inc.</FONT></H3>
  
    <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>
    
  </CENTER>
  </P></DIV><A NAME="_Toc519041910"></A><A NAME="Heading69"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
3: Debugging Techniques</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>Intro stuff</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Intro
stuff</FONT><A NAME="_Toc519041911"></A><BR></P></DIV>
<A NAME="Heading70"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Shared objects &amp; reference counting<A NAME="_Toc519041912"></A></H2></FONT>
<A NAME="Heading71"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Reference-counted class hierarchies<A NAME="_Toc519041913"></A></H2></FONT>
<A NAME="Heading72"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Debugging</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This section contains some tips and
techniques which may help during
debugging.</FONT><A NAME="_Toc519041914"></A><BR></P></DIV>
<A NAME="Heading73"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Trace macros</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Sometimes it&#8217;s very helpful to
print the code of each statement before it is executed, either to <B>cout</B> or
to a trace file. Here&#8217;s a preprocessor macro to accomplish
this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#define TRACE(ARG) cout &lt;&lt; #ARG &lt;&lt; endl; ARG</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Now you can go through and surround the
statements you trace with this macro. Of course, it can introduce problems. For
example, if you take the statement:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 100; i++)
  cout &lt;&lt; i &lt;&lt; endl;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">And put both lines inside
<B>TRACE(&#160;)</B> macros, you get this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>TRACE(<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 100; i++))
TRACE(  cout &lt;&lt; i &lt;&lt; endl;)</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Which expands to this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>cout &lt;&lt; <font color=#004488>"for(int i = 0; i &lt; 100; i++)"</font> &lt;&lt; endl;
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 100; i++)
  cout &lt;&lt; <font color=#004488>"cout &lt;&lt; i &lt;&lt; endl;"</font> &lt;&lt; endl;
cout &lt;&lt; i &lt;&lt; endl;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Which isn&#8217;t what you want. Thus,
this technique must be used carefully.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A variation on the <B>TRACE(&#160;)</B>
macro is this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#define D(a) cout &lt;&lt; #a <font color=#004488>"=["</font> &lt;&lt; a &lt;&lt; <font color=#004488>"]"</font> &lt;&lt; nl;</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If there&#8217;s an expression you want
to display, you simply put it inside a call to <B>D(&#160;)</B> and the
expression will be printed, followed by its value (assuming there&#8217;s an
overloaded operator <B>&lt;&lt;</B> for the result type). For example, you can
say <B>D(a + b)</B>. Thus you can use it anytime you want to test an
intermediate value to make sure things are OK.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Of course, the above two macros are
actually just the two most fundamental things you do with a debugger: trace
through the code execution and print values. A good debugger is an excellent
productivity tool, but sometimes debuggers are not available, or it&#8217;s not
convenient to use them. The above techniques always work, regardless of the
situation.</FONT><A NAME="_Toc519041915"></A><BR></P></DIV>
<A NAME="Heading74"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Trace file</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This code allows you to easily create a
trace file and send all the output that would normally go to <B>cout</B> into
the file. All you have to do is <B>#define</B> TRACEON and include the header
file (of course, it&#8217;s fairly easy just to write the two key lines right
into your file):</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C03:Trace.h</font>
<font color=#009900>// Creating a trace file</font>
#ifndef TRACE_H
#define TRACE_H
#include &lt;fstream&gt;

#ifdef TRACEON
ofstream TRACEFILE__(<font color=#004488>"TRACE.OUT"</font>);
#define cout TRACEFILE__
#endif

#endif <font color=#009900>// TRACE_H ///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here&#8217;s a simple test of the above
file:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C03:Tracetst.cpp</font>
<font color=#009900>// Test of trace.h</font>
#include <font color=#004488>"..</font><font color=#004488>/require.h"</font>
#include &lt;iostream&gt;
#include &lt;fstream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

#define TRACEON
#include <font color=#004488>"Trace.h"</font>

<font color=#0000ff>int</font> main() {
  ifstream f(<font color=#004488>"Tracetst.cpp"</font>);
  assure(f, <font color=#004488>"Tracetst.cpp"</font>);
  cout &lt;&lt; f.rdbuf();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This also uses the <B>assure(&#160;)</B>
function defined earlier in the
book.</FONT><A NAME="_Toc519041916"></A><BR></P></DIV>
<A NAME="Heading75"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Abstract base class for debugging</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the Smalltalk tradition, you can
create your own object-based hierarchy, and install pure virtual functions to
perform debugging. Then everyone on the team must inherit from this class and
redefine the debugging functions. All objects in the system will then have
debugging functions available.</FONT><A NAME="_Toc519041917"></A><BR></P></DIV>
<A NAME="Heading76"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Finding memory leaks</H2></FONT>
<OL>
<LI><FONT FACE="Georgia">	For array bounds checking, use the <B>Array</B>
template in C16:Array3.cpp of Volume 1 for all arrays. You can turn off the
checking and increase efficiency when you&#8217;re ready to ship. (This
doesn&#8217;t deal with the case of taking a pointer to an array, though &#8211;
perhaps that could be templatized somehow as
well).</FONT><LI><FONT FACE="Georgia">	Use the C11:MemCheck to guarantee that
dynamic memory is released properly.</FONT><LI><FONT FACE="Georgia">	Check for
non-virtual destructors in base
classes.</FONT><A NAME="_Toc519041918"></A></OL><A NAME="Heading77"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Tracking new/delete &amp; malloc/free</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Common problems with memory allocation
include calling <B>delete</B> for things you have <B>malloc</B>ed, calling
<B>free</B> for things you allocated with <B>new</B>, forgetting to release
objects from the free store, and releasing them more than once. This section
provides a system to help you track these kinds of problems
down.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To use the memory checking system, you
simply link the <B>obj</B> file in and all the calls to <B>malloc(&#160;)</B>,
<B>realloc(&#160;)</B>, <B>calloc(&#160;)</B>, <B>free(&#160;)</B>, <B>new</B>
and <B>delete</B> are intercepted. However, if you also include the following
file (which is optional), all the calls to <B>new</B> will store information
about the file and line where they were called. This is accomplished with a use
of the <I>placement syntax</I> for <B>operator new</B> (this trick was suggested
by Reg Charney of the C++ Standards Committee). The placement syntax is intended
for situations where you need to place objects at a specific point in memory.
However, it allows you to create an <B>operator new</B> with any number of
arguments. This is used to advantage here to store the results of the
<B>__FILE__</B> and <B>__LINE__</B> macros whenever <B>new</B> is
called:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C03:MemCheck.h</font>
<font color=#009900>// Memory testing system</font>
<font color=#009900>// This file is only included if you want to</font>
<font color=#009900>// use the special placement syntax to find</font>
<font color=#009900>// out the line number where "new" was called.</font>
#ifndef MEMCHECK_H
#define MEMCHECK_H
#include &lt;cstdlib&gt;  <font color=#009900>// size_t</font>

<font color=#009900>// Use placement syntax to pass extra arguments.</font>
<font color=#009900>// From an idea by Reg Charney:</font>
<font color=#0000ff>void</font>* <font color=#0000ff>operator</font> <font color=#0000ff>new</font>(
  std::size_t sz, <font color=#0000ff>char</font>* file, <font color=#0000ff>int</font> line);
#define <font color=#0000ff>new</font> <font color=#0000ff>new</font>(__FILE__, __LINE__)

#endif <font color=#009900>// MEMCHECK_H ///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the following file containing the
function definitions, you will note that everything is done with standard IO
rather than iostreams. This is because, for example, the <B>cout</B> constructor
allocates memory. Standard IO ensures against cyclical conditions that can lock
up the system.</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C03:MemCheck.cpp {O}</font>
<font color=#009900>// Memory allocation tester</font>
<font color=#009900>//{-msc}</font>
#include &lt;cstdlib&gt;
#include &lt;cstring&gt;
#include &lt;cstdio&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#009900>// MemCheck.h must not be included here</font>

<font color=#009900>// Output file object using cstdio</font>
<font color=#009900>// (cout constructor calls malloc())</font>
<font color=#0000ff>class</font> OFile {
  FILE* f;
<font color=#0000ff>public</font>:
  OFile(<font color=#0000ff>char</font>* name) : f(fopen(name, <font color=#004488>"w"</font>)) {}
  ~OFile() { fclose(f); }
  <font color=#0000ff>operator</font> FILE*() { <font color=#0000ff>return</font> f; }
};
<font color=#0000ff>extern</font> OFile memtrace;

⌨️ 快捷键说明

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