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

📄 http:^^www.cs.wisc.edu^~cs367-3^gdb.html

📁 This data set contains WWW-pages collected from computer science departments of various universities
💻 HTML
📖 第 1 页 / 共 3 页
字号:
Date: Tue, 05 Nov 1996 20:52:02 GMTServer: NCSA/1.5Content-type: text/htmlLast-modified: Tue, 10 Sep 1996 15:52:24 GMTContent-length: 32411<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<html>

<head>
<title>Debugging Using GDB</title>
<!-- Changed by: James Larus, 10-Sep-1996 --><meta name="GENERATOR" content="Microsoft FrontPage 1.1">
</head>

<body>
<!-- Changed by: James Larus, 10-Sep-1996 --><h1 align=center>Debugging Using GDB</h1>
<h4 align=center>(http://www.cs.wisc.edu/~cs367-3/gdb.html)</h4>
<h2 align=center>Authors: Charles Fischer, Tom Reps, James Larus, ....</h2>
<p>Look <!WA0><a href="http://www.cs.wisc.edu/~cs367-3/gdb">here</a> for the example programs that accompany this document. </p>
<hr>
<h2>Contents</h2>
<ul>
<li><!WA1><a href="#introduction">Introduction</a></li>
<li><!WA2><a href="#whatis">GDB and Debugging</a></li>
<li><!WA3><a href="#using_crashed">Using GDB on a Program that Crashed</a> </li>
<li><!WA4><a href="#incorrect_output">Using Gdb on a Program that Produces Incorrect Output</a> </li>
<li><!WA5><a href="#additional_commands">Additional Gdb Commands</a> </li>
<li><!WA6><a href="#command_summary">Summary of Gdb Commands</a> </li>
</ul>
<hr>
<h2><a name="introduction">Introduction</a></h2>
<p>Once you've written your program and it correctly compiles, you must thoroughly test it. Most newly written programs contain errors (or &quot;bugs&quot;) that must be 
discovered and corrected. This process is debugging. While testing your program, you can encounter two forms of bugs: (1) the program fails to terminate as 
expected and &quot;crashes&quot; instead, or (2) the program doesn't crash, but it produces unexpected or incorrect output. <tt>gdb</tt> is a debugger that can save large 
amounts of your time and frustration by helping you find both types of bugs quickly and easily.</p>
<p>When a program crashes, if you run the program under the control of <code>gdb</code>, you will get a chance to inspect the state of the program at the moment it crashed. 
When a program doesn't crash, but instead produces unexpected or incorrect output, again, you can run the program under the control of <code>gdb</code> to find the 
errors that cause the incorrect output. </p>
<p>Sometimes a program produces incorrect output that is wrong in rather subtle ways. For example a numeric result may differ only slightly from the correct 
answer. Sometimes a program may fail only rarely, usually giving correct output. It is the job of a programmer to thoroughly test a program before releasing it 
to users. This may involve creating a &quot;suite&quot; of standard tests that the program must handle flawlessly. If you are not sure that you can always recognize 
correct output, you may need to write additional code that verifies that the program really produces correct output. For example, if you were computing 
square roots, you might square the root and compare it against the original value. For complex calculations, it is sometimes a good idea to code a second 
independent solution of the problem in the test code, and compare the results the two solutions produce. If both produce the same answers over all tests, it is 
usually reasonable to assume that the answers are correct. </p>
<h2><a name="whatis">GDB and Debugging</a></h2>
<p><code>Gdb</code> is a programming tool available in most Unix systems for debugging C and C++ programs. If you plan to use <code>gdb</code> to debug your programs, you must 
compile all source files using the <code>&quot;-g&quot;</code> option (for debu<b>g</b>). This option produces tables that the debugger needs.</p>
<p>Moreover, there is an X-windows version of <tt>gdb</tt> called <tt>xxgdb</tt>, which has a window interface that you may find to be a lot easier and more pleasent to use. 
However, this program is difficult to describe in words, so this document explains the plain version of <tt>gdb</tt>. All commands also work in <tt>xxgdb</tt>; you just click 
a button instead of typing them in.</p>
<p>However, let's first note that the fastest and best way to use a debugger is to not use it at all! In many cases, careful examination of a program's output gives a 
great deal of information about what went wrong. For example, if the program crashed, it must have been in that portion of the program between the last 
output that was produced and the first expected output that <em>wasn't</em> produced. (However, note that many systems &quot;buffer&quot; output, so it sometimes happens 
that a program may produce part of an output line that was never printed because of the program crashed. <code>cout.flush()</code> forces buffered output to be 
immediately printed.) </p>
<p>Even if a program doesn't crash, careful examination of a program's output can reveal patterns of correct and incorrect values that may well indicate likely 
errors. When you get incorrect outputs don't panic. Calmly look at what was produced, and try to reason about what went wrong. Use an editor to examine 
the parts of your program that are most likely to be responsible for the errors. If you still can't explain what went wrong, it may be time to use <code><tt>gdb</tt></code> or <tt>xxgdb</tt> 
to gather more information. </p>
<h2><a name="using_crashed">Using GDB on a Program that Crashed </a></h2>
<p>A program crashes when it encounters an error so severe that further execution is impossible. The Unix operating system prints a message saying what 
caused the program to terminate and then kills the program. The termination message is rarely specific or helpful. Common messages are: <code>segmentation 
fault</code> and <code>bus error</code>, which usually indicate that an invalid array access or pointer reference occurred. </p>
<p>In this section we'll show how <code>gdb</code> can be used to discover the reason why a program has crashed. To illustrate using <code>gdb</code> after a crash, we'll use the 
following simple C++ program, <!WA7><a href="http://www.cs.wisc.edu/~cs367-3/gdb/bug1.C"><code>bug1.C</code></a>, which tries to allocate, initialize, and print an array of strings (the line numbers are for reference purposes): </p>
<pre><code><samp>1   # include &lt;iostream.h&gt;
2   
3   /* Allocate, initialize, and print an array of strings */
4   void init (char *str)
5   {
6     int i;
7   
8     for (i = 1; i &lt;= i++)
9       {
10         *(str++) = 'x';
11      }
12    *str = '\0';
13   }
14
15  int main()
16  {
17    int j, i;
18    char strs[4];
19
20    for (i= 1; i &lt;= 4; i++)
21      {
22        strs[i] = new char[11];
23      }
24
25    for (i= 1; i &lt;= 4; i++)
26      {
27        init(strs[i]);
28      }
29
30    for (i= 1; i &lt;= 4; i++)
31      {
32        cout &lt;&lt; strs[j] &lt;&lt; endl;
33      }
34
35    return 0;
36  }</samp></code></pre>
<p><samp>When we compile and execute </samp><code><samp>bug1.C</samp></code><samp>, the program crashes before printing any output, and we get the following message: </samp></p>
<p><code><samp>Segmentation fault (core dumped)</samp></code><samp> </samp></p>
<p><samp>We have no idea of what went wrong, so it's time to use </samp><code><samp>gdb</samp></code><samp>. We need to re-run the program under the control of </samp><code><samp>gdb</samp></code><samp>: </samp></p>
<pre><code><samp>&gt; gdb bug1
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type &quot;show copying&quot; to see the conditions.
There is absolutely no warranty for GDB; type &quot;show warranty&quot; for details.
GDB 4.13 (sparc-sun-sunos4.1.3), 
Copyright 1994 Free Software Foundation, Inc...
(gdb) run
Starting program: /afs/cs.wisc.edu/p/course/cs367-reps/private/GDB/bug1

Program received signal SIGSEGV, Segmentation fault.
0x15664 in init (str=0x5 &lt;Address 0x5 out of bounds&gt;) at bug1.C:10
10	    *(str++) = 'x';
(gdb)</samp></code></pre>
<p><code>Gdb</code> tells us that execution terminated in function <code>init</code> at line 10 of file <code>bug1.C</code>. It also shows us that source line (the number at the extreme left is a line 
number). The line </p>
<p><code>(gdb)</code> </p>
<p>is a prompt; <code>gdb</code> is waiting for us to give a command. A good start is the <code>where</code> command, which will tell us more about the context in which the crash 
occurred: </p>
<pre><code><samp>(gdb) where
#0  0x15664 in init (str=0x5 &lt;Address 0x5 out of bounds&gt;) at bug1.C:10
#1  0x15730 in main () at bug1.C:27
(gdb)</samp></code></pre>
<p>This shows the <em>call stack</em>, the sequence of function calls in progress at the point of termination. The top of the list is the most recent call; the bottom is the 
original call. (Hexadecimal numbers, like 0x15664, are addresses that you'll normally ignore). Execution terminated in <code>init</code> (at line 10 of <code>bug1.C</code>), which 
was called by <code>main</code> at line 27 of <code>bug1.C</code>. </p>
<p>At this point we'll want to look at that part of our program around lines 10 and 27 of file <code>bug1.C</code>. <code>Gdb</code> has a command to list files (named <code>list</code>): </p>
<pre><code><samp>(gdb) list
5       {
6         int i;
7       
8     for (i = 1; i &lt;= i++)
9       {
10         *(str++) = 'x';
</samp></code></pre>
<p>(Sometimes you will want to create a new window and look at the file in question using your favorite editor -- after all, you'll probably want to correct the 
bugs once you find them!) </p>
<p>Looking at line 10 (in the listing of <code>bug1.C</code> shown above), we see there is an assignment to a character pointed to by variable <code>str</code>. Let's print out the values 
of <code>str</code> and <code>*str</code> to see if they seem reasonable.	The command to print a value is <code>print</code>, which can be abbreviated as <code>p</code>. </p>
<pre><code><samp>(gdb) p str
$1 = 0x5 </samp></code></pre>
<pre>&lt;address x5 out of bounds&gt;<code><samp>
(gdb) p *str Cannot access memory at address 0x5. </samp></code></pre>
<p>Pointer variable <code>str</code> has the value <code>0x5</code>. This address (which <code>gdb</code> has reported to us in hexadecimal format) looks suspicious because pointers are usually 
very large values. In fact, when we look at the value <code>*str</code> this confirms our suspicion: <code>gdb</code> tells us we cannot access memory at that address. (The symbols 
on the left of the equal sign, starting with a $, are internal variables <code>gdb</code> stores with the values that were printed). Now we know why execution was 
terminated -- we tried to assign a value through a bad pointer. </p>
<p>Our problem now is to figure out why <code>str</code> was assigned a bad address. </p>
<p>We look at the value of <code>i</code> to see how far the loop has progressed: </p>
<pre><code><samp>(gdb) p i
$2 = 1</samp></code></pre>
<p>The value of <code>i</code> is only <code>1</code>, so the loop just started. <code>Init</code> was probably passed a bad pointer by its caller. To find out information about the caller, we must tell 
<code>gdb</code> to focus on another point in the call stack -- the caller of <code>init</code>. The command <code>up</code> will take us up one call (<code>down</code> takes us back down the call stack): </p>
<pre><code><samp>(gdb) up
#1  0x23a4 in main () at bug1.C:27

⌨️ 快捷键说明

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