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

📄 ch24.htm

📁 VC使用所有细节的逻列
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<P><I>The Project Settings dialog box enables you to set configuration items for different phases of development.</I></P>

<ol start=3>

<li><P> Click the C/C++ tab and set the Warning <U>L</U>evel to Level 4, as shown in Figure 24.2. The default is Level 3, which we will use for the release version (see Figure 20.3).</P>

</ol>

<A HREF="Yfigs02.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch24/Yfigs02.gif"><b>Fig. 24.2</b></A>

<P><I>Warning levels can be set higher during development.</I></P>

<A HREF="Yfigs03.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch24/Yfigs03.gif"><b>Fig. 24.3</b></A>

<P><I>Warning levels are usually lower in a production release.</I></P>

<H3><A ID="I7" NAME="I7"><B>Sealing Memory Leaks</B></A></H3>

<P>A memory leak can be the most pernicious of errors. Small leaks may not cause any execution errors in your program until it is run for an exceptionally long time or with a larger-than-usual data file. Because most programmers test with tiny data files, 
or run the program for only a few minutes when they are experimenting with parts of it, memory leaks may not reveal themselves in everyday testing. Alas, memory leaks may well reveal themselves to your users when the program crashes or otherwise 
misbehaves.</P>

<P><A ID="I8" NAME="I8"><B>Common Causes of Memory Leaks</B></A></P>

<P>What does it mean when your program has a memory leak? It means that your program allocated memory and never released it. One very simple cause is calling <font color="#008000">new</font> to allocate an object or an array of objects on the heap, and 
never calling <font color="#008000">delete</font>. Another cause of memory leaks is to change the pointer kept in a variable without deleting the memory the pointer was pointing to. More subtle memory leaks arise when a class with a pointer as a member 
variable calls <font color="#008000">new</font> to assign the pointer, but doesn&#146;t have a copy constructor, assignment operator, or destructor. Listing 24.1 illustrates some ways that memory leaks are caused.</P>

<P><I>Listing 24.1&#151;Causing Memory Leaks</I></P>

<pre><font color="#008000">// simple pointer leaving scope</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">  int * one = new int;</font></pre>

<pre><font color="#008000">  *one = 1;</font></pre>

<pre><font color="#008000">} // one is out of scope now, and wasn&#146;t deleted</font></pre>

<pre><font color="#008000">// mismatched new and delete: new uses delete and new[] uses delete[]</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">float * f = new float[10];</font></pre>

<pre><font color="#008000">// use array</font></pre>

<pre><font color="#008000">delete f; // Oops! Deleted f[0] correct version is delete [] f;</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">// pointer of new memory goes out of scope before delete</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    const char * DeleteP = &#147;Don&#146;t forget P&#148;;</font></pre>

<pre><font color="#008000">    char * p = new char[strlen(DeleteP) + 1];</font></pre>

<pre><font color="#008000">    strcpy( p, DeleteP );</font></pre>

<pre><font color="#008000">} // scope ended before delete[]</font></pre>

<pre><font color="#008000">class A</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">   public:</font></pre>

<pre><font color="#008000">      int * pi;</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">A::A()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    pi = new int();</font></pre>

<pre><font color="#008000">    *pi = 3;</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">//  ..later on, some code using this class..</font></pre>

<pre><font color="#008000">A firsta;   //allocates an int for first.pi to point to</font></pre>

<pre><font color="#008000">B seconda;  //allocates another int for seconda.pi</font></pre>

<pre><font color="#008000">seconda=firsta;</font></pre>

<pre><font color="#008000">// will perform a bitwise copy. Both objects have</font></pre>

<pre><font color="#008000">// a pi that points to the first int allocated. The </font></pre>

<pre><font color="#008000">// pointer to the second int allocated is gone forever.</font></pre>

<P>The code fragments all represent ways in which memory can be allocated and the pointer to that memory lost before deallocation. Once the pointer goes out of scope, you cannot reclaim the memory and no one else can use it either. Things get even worse 
when you consider exceptions, discussed in <A HREF="index26.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index26.htm" target="text">Chapter 26</A>, &#147;Exceptions, Templates, and the Latest Additions to C++,&#148; because if an exception is thrown, your flow of execution may leave a function before 
reaching the <font color="#008000">delete</font> at the bottom of the code. Because destructors are called for objects that are going out of scope as the stack unwinds, you can prevent some of these problems by putting <font color="#008000">delete</font> 
calls in destructors. This is also discussed in more detail in <A HREF="index26.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index26.htm" target="text">Chapter 26</A>, in the &quot;Placing the Catch Block&quot; section.</P>

<P>Like all bugs, the secret to dealing with memory leaks is to prevent them, or to detect them as early as possible when they occur. You can develop some good habits to help you:</P>

<ul>

<li> If a class contains a pointer, and allocates that pointer with <font color="#008000">new</font>, be sure to code a destructor that <font color="#008000">delete</font>s the memory. Also code a copy constructor and an operator (<font 
color="#008000">=</font>).</P>

<li> If a function will allocate memory and return something to let the calling program access that memory, it must return a pointer rather than a reference. You cannot <font color="#008000">delete</font> a reference.</P>

<li> If a function will allocate memory and then <font color="#008000">delete</font> it later in the same function, allocate the memory on the stack if at all possible, so that you do not forget to <font color="#008000">delete</font> it.</P>

<li> Never change the value of a pointer unless you have first <font color="#008000">delete</font>d the object or array it was pointing to. Never increment a pointer that was returned by <font color="#008000">new</font>.</P>

</ul>

<P><A ID="I9" NAME="I9"><B>Debug </B><B><I>new</I></B><B> and </B><B><I>delete</I></B></A></P>

<P>MFC has a lot to offer the programmer who is looking for memory leaks. In debug builds, whenever you use <font color="#008000">new</font> and <font color="#008000">delete</font> you are actually using special debug versions, that track the file number 
and line on which each allocation occurred, and that match up <font color="#008000">delete</font>s with their <font color="#008000">new</font>s. If memory is left over as the program ends, you get a warning message in the output section, as shown in Figure 
24.4.</P>

<A HREF="Yfigs04.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch24/Yfigs04.gif"><b>Fig. 24.4</b></A>

<P><I>Memory leaks are detected automatically in debug builds.</I></P>

<P>To see this for yourself, create an AppWizard MDI application called Leak, accepting all the defaults. In the <font color="#008000">InitInstance()</font> function of the application class (<font color="#008000">CLeakApp</font> in this example), add 
this line:</P>

<pre><font color="#008000">int* pi = new int[20];</font></pre>

<P>Build a debug version of the application and run it by choosing <U>B</U>uild, Start <U>D</U>ebug, <U>G</U>o, or click the Go button on the Build mini-bar. You should see output like Figure 24.4. Notice that the file name (Leak.cpp) and line number 
where the memory was allocated are provided in the error message. The editor window displays Leak.cpp with the cursor on line 54. (The coordinates in the lower-right corner remind you what line number you are on at all times.) If you were writing a real 
application you would now know what the problem was. The next problem to tackle is where to fix it (more specifically, where to put the <font color="#008000">delete</font>).</P>

<P><A ID="I10" NAME="I10"><B>Automatic Pointers</B></A></P>

<P>When a program is executing within a particular scope, like a function, all variables allocated in that function are allocated on the stack. The <I>stack</I> is a temporary storage space that shrinks and grows, like an accordion. The stack is used to 
store the current execution address prior to a function call, the arguments passed to the function, and the local function objects and variables.</P>

<P>When the function returns, the <I>stack pointer</I> is reset to that location where the prior execution point was stored. This makes the stack space after the reset location available to whatever else needs it, which means those elements allocated on 
the stack in the function are gone. This process is referred to as <I>stack unwinding.</I></P>

<blockquote><p><img src="note.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/note.gif">

<P>Objects or variables defined with the keyword <font color="#008000">static</font> are not allocated on the stack.</P>

<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>

<P>Stack unwinding also happens when an exception occurs. To reliably restore the program to its state before an exception occurred in the function, the stack is unwound. Stack-wise variables are gone and the destructors for stack-wise objects are called 
and are also gone. Unfortunately, the same is <I>not</I> true for dynamic objects. The handles (for example, pointers) are unwound but <font color="#008000">delete</font> is not called by the unwinding process. This causes a memory leak.</P>

<P>In some cases, the solution is to add <font color="#008000">delete</font> statements to the destructors of objects that you know will be destructed as part of the unwinding, so that they can use these pointers before they go out of scope. A more 
general approach is to replace simple pointers with a C++ class that can be used just like a pointer, but contains a destructor that <font color="#008000">delete</font>s any memory at the location where it points. Don&#146;t worry, you don&#146;t have to 
write such a class: one is included in the Standard Template Library, which comes with Visual C++. Listing 24.2 is a heavily edited version of the <font color="#008000">auto_ptr</font> class definition, presented to demonstrate the key concepts.</P>

<blockquote><p><img src="tip.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/tip.gif">

<P>If you haven&#146;t seen template code before, it&#146;s explained in <A HREF="index26.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index26.htm" target="text">Chapter 26</A>, &#147;Exceptions, Templates, and the Latest Additions to C++.&#148;</P>

⌨️ 快捷键说明

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