📄 ch27.htm
字号:
<P><TT>gdb</TT> will return the following acknowledgment:</P>
<PRE><FONT COLOR="#0066FF">Watchpoint 2: string2[size - i]
</FONT></PRE>
<P>The version of <TT>gdb</TT> included on the CD-ROM accompanying this book changes
the prompt to <TT>Hardware Watchpoint</TT>, but this is simply a change in the naming
convention used by <TT>gdb</TT>. Now you can step through the execution of the <TT>for</TT>
loop using the <TT>next</TT> command:</P>
<PRE><FONT COLOR="#0066FF">(gdb) next
</FONT></PRE>
<P>After the first time through the loop, <TT>gdb</TT> tells us that <TT>string2[size
- i]</TT> is <TT>`h'</TT>. <TT>gdb</TT> informs you of this by writing the following
message on the screen:</P>
<PRE><FONT COLOR="#0066FF">Watchpoint 2, string2[size - i]
Old value = 0 `\000'
New value = 104 `h'
my_print2(string = 0xbfffdc4 "hello there") at greeting.c:23
23 for (i=0; i<size; i++)
</FONT></PRE>
<DL>
<DT><FONT COLOR="#0066FF"></FONT></DT>
</DL>
<DL>
<DD>
<HR>
<A NAME="Heading17<FONT COLOR="#000077"><B>NOTE:</B> </FONT>The version of
<TT>gcc</TT> on the CD-ROM accompanying this book appears to have some bugs in the
<TT>include</TT> files. Some tasks, including checking the next watchpoint, cause
error messages. You should check the FTP sites for updates or previous versions which
do not have this fault if this presents a problem for your C compiler usage.
<HR>
</DL>
<P>This is the value that you expected. Stepping through the loop several more times
reveals similar results. Everything appears to be functioning normally. When you
get to the point where <TT>i=10</TT>, the value of the <TT>string2[size - i]</TT>
expression is equal to <TT>`e'</TT>, the value of the <TT>size - i</TT> expression
is equal to 1, and the program is at the last character that is to be copied over
into the new string.</P>
<P>If you step through the loop one more time, you see that there was not a value
assigned to <TT>string2[0]</TT>, which is the first character of the string. Because
the <TT>malloc</TT> function initializes the memory it assigns to null, the first
character in <TT>string2</TT> is the null character. This explains why nothing was
being printed when you tried to print <TT>string2</TT>.</P>
<P>Now that you have found the problem, it should be quite easy to fix. You must
write the code so that the first character going into <TT>string2</TT> is being put
into <TT>string2</TT> at offset <TT>size - 1</TT> instead of <TT>string2</TT> at
offset <TT>size</TT>. This is because the size of <TT>string2</TT> is 12, but it
starts numbering at offset zero. The characters in the string should start at offset
0 and go to offset 10, with offset 11 being reserved for the null character.</P>
<P>There are many ways to modify this code so that it will work. One way is to keep
a separate size variable that is one smaller than the real size of the original string.
This solution is shown in the following code:</P>
<PRE><FONT COLOR="#0066FF">#include <stdio.h>
main ()
{
char my_string[] = "hello there";
my_print (my_string);
my_print2 (my_string);
}
my_print (char *string)
{
printf ("The string is %s\n", string);
}
my_print2 (char *string)
{
char *string2;
int size, size2, i;
size = strlen (string);
size2 = size -1;
string2 = (char *) malloc (size + 1);
for (i = 0; i < size; i++)
string2[size2 - i] = string[i];
string2[size] = `\0';
printf ("The string printed backward is %s\n", string2);
}
</FONT></PRE>
<CENTER>
<H3><A NAME="Heading18<FONT COLOR="#000077">Additional C Programming Tools</FONT></H3>
</CENTER>
<P>The Slackware Linux distribution includes a number of C development tools that
have not yet been described. This section describes many of these additional tools
and their typical uses.
<CENTER>
<H4><A NAME="Heading19<FONT COLOR="#000077">xxgdb</FONT></H4>
</CENTER>
<P><TT>xxgdb</TT> is an X Window system-based graphical user interface to <TT>gdb</TT>.
All of the features that exist in the command-line version of <TT>gdb</TT> are present
in <TT>xxgdb</TT>. <TT>xxgdb</TT> enables you to perform many of the most commonly
used <TT>gdb</TT> commands by pressing buttons instead of typing commands. It also
graphically represents where you have placed breakpoints.</P>
<P>You can start <TT>xxgdb</TT> by typing the following into an <TT>Xterm</TT> window.</P>
<PRE><FONT COLOR="#0066FF">xxgdb
</FONT></PRE>
<P>When you initiate <TT>xxgdb</TT>, you can specify any of the command-line options
that were available with <TT>gdb</TT>. The <TT>xxgdb</TT> program also has some of
its own command-line options. These are described in Table 27.2. </P>
<CENTER>
<P><FONT SIZE="4"><B>Table 27.2. The xxgdb command-line options. </B></FONT>
<TABLE BORDER="0">
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="70" ALIGN="LEFT"><I>Option</I></TD>
<TD ALIGN="LEFT"><I>Description</I></TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="70" ALIGN="LEFT"><TT>db_name</TT></TD>
<TD ALIGN="LEFT">Specifies the name of the debugger to be used. The default is <TT>gdb</TT>.</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="70" ALIGN="LEFT"><TT>db_prompt</TT></TD>
<TD ALIGN="LEFT">Specifies the debugger prompt. The default is <TT>gdb</TT>.</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="70" ALIGN="LEFT"><TT>gdbinit</TT></TD>
<TD ALIGN="LEFT">
<P ALIGN="CENTER">Specifies the filename of the initial <TT>gdb</TT> command file.
The default is <TT>.gdbinit</TT>.
</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="70" ALIGN="LEFT"><TT>nx</TT></TD>
<TD ALIGN="LEFT">Tells <TT>xxgdb</TT> not to execute the <TT>.gdbinit</TT> file.</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="70" ALIGN="LEFT"><TT>bigicon</TT></TD>
<TD ALIGN="LEFT">Uses a large icon size for the <TT>xxgdb</TT> icon.</TD>
</TR>
</TABLE>
</P>
</CENTER>
<P><BR>
When you start <TT>xxgdb</TT>, a window opens on your screen. This window is shown
in Figure 27.1.</P>
<P>The <TT>xxgdb</TT> main window contains a message that is similar to the one displayed
on the screen when you start the command-line version of <TT>gdb</TT>. Near the bottom
of the <TT>xxgdb</TT> main window there are four buttons. The Source Listing, Command
Buttons, and Display Window buttons each bring up an additional window when they
are activated. The Quit button terminates the <TT>xxgdb</TT> program.<BR>
<BR>
<A NAME="Heading20<A HREF="../art/27/27lnx01.jpg"><FONT COLOR="#000077"><B>FIGURE
27.1.</B></FONT></A><I> The <TT>xxgdb</TT> main window.</I><BR>
<BR>
The Source Listing button brings up a window that will display the source code for
the program that is being debugged. This window is shown in Figure 27.2.</P>
<P>The Command Buttons button brings up a window that contains 26 other buttons.
These buttons each execute a <TT>gdb</TT> command. The <TT>gdb</TT> command-button
window is illustrated in Figure 27.3.</P>
<P>The Display Window button brings up a window that is used to display the results
of any display command. You can tell <TT>xxgdb</TT> what variable or expression to
display by selecting it from the source listing and then clicking on the Display
button in the command-button window. The display window is illustrated in Figure
27.4.</P>
<P>For more information on using <TT>xxgdb</TT>, refer to the <TT>xxgdb</TT> manual
page and the <TT>gdb</TT> manual page.<BR>
<BR>
<A NAME="Heading21<A HREF="../art/27/27lnx02.jpg"><FONT COLOR="#000077"><B>FIGURE
27.2.</B></FONT></A><I>The <TT>xxgdb</TT> source listing window</I><FONT COLOR="#000077">.</FONT><BR>
<BR>
<A NAME="Heading22<A HREF="../art/27/27lnx03.jpg"><FONT COLOR="#000077"><B>FIGURE
27.3.</B></FONT></A><FONT COLOR="#000077"> </FONT><I>The <TT>xxgdb</TT> command-button
window.</I><BR>
<BR>
<A NAME="Heading23<A HREF="../art/27/27lnx04.jpg"><FONT COLOR="#000077"><B>FIGURE
27.4.</B></FONT></A><FONT COLOR="#000077"> </FONT><I>The <TT>xxgdb</TT> display window.</I>
<CENTER>
<H4><A NAME="Heading24<FONT COLOR="#000077">calls</FONT></H4>
</CENTER>
<P><TT>calls</TT> is a program that is not included on the Linux CD-ROM accompanying
this book, but you can obtain a copy from the <TT>sunsite.unc.edu</TT> FTP site under
the directory <TT>/pub/Linux/devel/lang/c/calls.tar.Z</TT>. Some older CD-ROM distributions
of Linux include this file. Because it is a useful tool, we will cover it here. If
you think it will be of use to you, obtain a copy from an FTP or BBS site or another
CD-ROM. <TT>calls</TT> runs the GCC preprocessor on the files that are passed to
it on the command line, and displays a function call tree for the functions that
are in those files.
<DL>
<DT></DT>
</DL>
<DL>
<DD>
<HR>
<A NAME="Heading25<FONT COLOR="#000077"><B>NOTE:</B> </FONT>To install <TT>calls</TT>
on your system, perform the following steps while you are logged in as root: 1. Uncompress
and <TT>untar</TT> the file. 2. <TT>cd</TT> into the <TT>calls</TT> subdirectory
that was created by <TT>untar</TT>ring the file. 3. Move the file named <TT>calls</TT>
to the <TT>/usr/bin</TT> directory. 4. Move the file named <TT>calls.1</TT> to the
<TT>/usr/man/man1</TT> directory. 5. Remove the <TT>/tmp/calls</TT> directory. This
will install the <TT>calls</TT> program and man page on your system.
<HR>
</DL>
<P>When <TT>calls</TT> prints out the call trace, it includes the filename in which
the function was found in brackets after the function name:</P>
<PRE><FONT COLOR="#0066FF">main [test.c]
</FONT></PRE>
<P>If the function was not in one of the files that was passed to <TT>calls</TT>,
it does not know where that function lives and prints only the function name:</P>
<PRE><FONT COLOR="#0066FF">printf
</FONT></PRE>
<P><TT>calls</TT> also makes note of recursive and static functions in its output.
Recursive functions are represented in the following way:</P>
<PRE><FONT COLOR="#0066FF">fact <<< recursive in factorial.c >>>
</FONT></PRE>
<P>Static functions are represented like this:</P>
<PRE><FONT COLOR="#0066FF">total [static in calculate.c]
</FONT></PRE>
<P>As an example, assume that you executed calls with the following program as input:</P>
<PRE><FONT COLOR="#0066FF">##include <stdio.h>
main ()
{
char my_string[] = "hello there";
my_print (my_string);
my_print2(my_string);
}
my_print (char *string)
{
printf ("The string is %s\n", string);
}
my_print2 (char *string)
{
char *string2;
int size, size2, i;
size = strlen (string);
size2 = size -1;
string2 = (char *) malloc (size + 1);
for (i = 0; i < size; i++)
string2[size2 - i] = string[i];
string2[size] = `\0';
printf ("The string printed backward is %s\n", string2);
}
</FONT></PRE>
<P>This would generate the following output:</P>
<PRE><FONT COLOR="#0066FF"> 1 main [test.c]
2 my_print [test.c]
3 printf
4 my_print2 [test.c]
5 strlen
6 malloc
7 printf
</FONT></PRE>
<DL>
<DT><FONT COLOR="#0066FF"></FONT></DT>
</DL>
<DL>
<DD>
<HR>
<A NAME="Heading26<FONT COLOR="#000077"><B>WARNING:</B> </FONT>The version
of <TT>gcc</TT> included with this book's CD-ROM may generate error messages running
this code. Again, you may want to check FTP sites for a more recent version or bug
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -