Red Hat Linux 9 Professional Secrets [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Red Hat Linux 9 Professional Secrets [Electronic resources] - نسخه متنی

Naba Barkakati

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








The GNU Debugger


Although

make automates the process of building a program, that task is the least of your worries when a program does not work correctly or when a program suddenly quits with an error message. You need a debugger to find the cause of program errors. This book's companion CD-ROMs include

gdb -the versatile GNU debugger with a command-line interface.

Like any debugger,

gdb lets you perform typical debugging tasks, such as the following:



  • Set the breakpoint so that program execution stops at a specified line.



  • Watch the values of variables in the program.



  • Step through the program one line at a time.



  • Change variables in an attempt to fix errors.



The gdb debugger can debug C and C++ programs.


Preparing a Program for Debugging


If you want to debug a program by using

gdb , you have to ensure that the compiler generates and places debugging information in the executable. The debugging information contains the names of variables in your program and the mapping of addresses in the executable file to lines of code in the source file. gdb needs this information to perform its functions, such as stopping after executing a specified line of source code.






Insider Insight

To ensure that the executable is properly prepared for debugging, use the

-g option with GCC. You can do this by defining the variable CFLAGS in the makefile as:

CFLAGS= -g



Running gdb


The most common way to debug a program is to run

gdb by using the following command:

gdb progname

progname is the name of the program's executable file. After it runs,

gdb displays the following message and prompts you for a command:

GNU gdb Red Hat Linux (5.3post-0.20021129.7rh)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
(gdb) help
List of classes of commands:
aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands
Type "help" followed by a class name for a list of commands in that class.
Type "help" followed by command name for full documentation.
Command name abbreviations are allowed if unambiguous.
(gdb) q

When you type help,

gdb displays the classes of

gdb commands. You can get further help on a specific class of commands or a specific command by following the instructions. To see the list of commands you use to run the program you are debugging, type help running at the gdb prompt.

To quit

gdb , type q, and press Enter.

gdb has a large number of commands, but you need only a few to find the cause of an error quickly. Table 23-4 lists the commonly used

gdb commands.


























































































Table 23-4: Commonly Used gdb Commands


Command


Description


break

NUM


Set a breakpoint at the specified line number (the debugger stops at breakpoints)


bt


Display a trace of all stack frames. (This command shows you the sequence of function calls so far.)


clear clear

FILENAME

:

NUM


Delete the breakpoint at a specific line in a source file. For example,

xdraw.c:8 clears the breakpoint at line 8 of file

xdraw.c .


Continue


Continue running the program being debugged. (Use this command after the program has stopped due to a signal or breakpoint.)


display

EXPR


Display value of expression (consisting of variables defined in the program) each time the program stops


file

FILE


Load specified executable file for debugging


help

NAME


Display help on the command named

NAME


info break


Display a list of current breakpoints, including information on how many times each breakpoint has been reached


info files


Display detailed information about the file being debugged


info func


Display all function names


info local


Display information about local variables of current function


info prog


Display the execution status of the program being debugged


info var


Display all global and static variable names


Kill


End the program you are debugging


List


List a section of the source code


Make


Run the

make utility to rebuild the executable without leaving

gdb


Next


Advance one line of source code in the current function without stepping into other functions


print

EXPR


Show the value of the expression

EXPR


Quit


Quit

gdb


Run


Start running the currently loaded executable


set variable


Set the value of the variable

VAR to

VALUE

VAR

=

VALUE


shell

CMD


Execute a Linux command

CMD , without leaving

gdb


Step


Advance one line in the current function, stepping into other functions, if any


watch

VAR


Show the value of the variable named

VAR whenever the value changes


Where


Display the call sequence. Use this command to locate where your program died.


x/F

ADDR


Examine the contents of the memory location at address

ADDR in the format specified by the letter

F , which can be

o (octal);

x (hex);

d (decimal);

u (unsigned decimal); t (binary);

f (float); a (address);

i (instruction);

c (char); or

s (string). You can append a letter indicating the size of data type to the format letter. Size letters are

b (byte);

h (halfword, 2 bytes),

w (word, 4 bytes); and

g (giant, 8 bytes). Typically,

ADDR is the name of a variable or pointer.



Finding Bugs by Using gdb


To understand how you can find bugs by using

gdb , you need to see an example. The procedure is easiest to show with a simple example, so I start with a rather contrived program that contains a typical bug.

This is the contrived program, which I store in the file

dbgtst.c :

#include <stdio.h>
static char buf[256];
void read_input(char *s);
int main(void)
{
char *input = NULL; /* Just a pointer, no storage for string */
read_input(input);
/* Process command. */
printf("You typed: %s\n", input);
/* ... */
return 0;
}
void read_input(char *s)
{
printf("Command: ");
gets(s);
}

This program's

main function calls the

read_input function to get a line of input from the user. The

read_input function expects a character array in which it returns what the user types. In this example, however,

main calls

read_input with an uninitialized pointer-that's the bug in this simple program.

Build the program by using

gcc with the

-g option:

gcc -g -o dbgtst dbgtst.c

Ignore the warning message about the

gets() function being dangerous; we are trying to use the shortcoming of the

gets() function to show how

gdb can be used to track down errors.

To see the problem with this program, run it:


./dbgtst
Command: test
Segmentation fault

The program dies after displaying the

Segmentation fault message. For this small program, you can find the cause by examining the source code. In a real-world application, however, you may not immediately know what causes the error. That's when you use

gdb to find the cause of the problem.

To use

gdb to locate a bug, follow these steps:



  1. Load the program under

    gdb . To load a program named

    dbgtst in

    gdb , type the following:

    gdb dbgtst



  2. At the (gdb) prompt, type run. When the program prompts for input, type some input text. The program should fail as it has previously. Here's what happens with the

    dbgtst program:

    (gdb) run
    Starting program: /home/naba/apps/dbgtst
    Command: test
    Program received signal SIGSEGV, Segmentation fault.
    0x420632cc in gets () from /lib/tls/libc.so.6
    (gdb)



  3. Type the

    where command to determine where the program died. For the

    dbgtst program, this command yields this output:

    (gdb) where
    #0 0x420632cc in gets () from /lib/tls/libc.so.6
    #1 0x080483bc in read_input (s=0x0) at dbgtst.c:22
    #2 0x0804837e in main () at dbgtst.c:10
    #3 0x420154a0 in __libc_start_main () from /lib/tls/libc.so.6
    (gdb)

    The output shows the sequence of function calls. Function call #0-the most recent one-is to a C library function,

    gets . The

    gets call originates in the

    read_input function, which in turn is called from the

    main function.



  4. Type the

    list command with the name of a file and line number to inspect the lines of suspect source code. In

    dbgtst , you might start with line 22 of

    dbgtst.c file, as follows:

    (gdb) list dbgtst.c:22
    17 }
    18
    19 void read_input(char *s)
    20 {
    21 printf("Command: ");
    22 gets(s);
    23 }
    24
    (gdb)

    After looking at this listing, if you have some experience writing C programs, you should be able to tell that the problem might be the way

    read_input is called. Then you list the lines around line 10 in

    dbgtst.c (where the

    read_input call originates):

    (gdb) list dbgtst.c:10
    5
    6 int main(void)
    7 {
    8 char *input = NULL; /* Just a pointer, no storage for string */
    9
    10 read_input(input);
    11
    12 /* Process command. */
    13 printf("You typed: %s\n", input);
    14
    (gdb)

    At this point, you should be able to narrow the problem to the variable named

    input . That variable should be an array, not a NULL pointer.




Fixing Bugs in gdb


Sometimes you can try a bug fix directly in

gdb . For the example program in the preceding section, you can try this fix immediately after the program dies after displaying an error message. Because the example is contrived, I have an extra buffer named

buf defined in the

dbgtst program, as follows:

static char buf[256];

I can fix the problem of the uninitialized pointer by setting the variable

input to

buf . The following session with

gdb corrects the problem of the uninitialized pointer (this example picks up immediately after the program has run and died, due to the segmentation fault):

 (gdb) file dbgtst
A program is being debugged already. Kill it? (y or n) y
Load new symbol table from "dbgtst"? (y or n) y
Reading symbols from dbgtst...
done.
(gdb) list
1 #include <stdio.h>
2
3 static char buf[256];
4 void read_input(char *s);
5
6 int main(void)
7 {
8 char *input = NULL; /* Just a pointer, no storage for string
*/
9
10 read_input(input);
(gdb) break 9
Breakpoint 1 at 0x8048373: file dbgtst.c, line 9.
(gdb) run
Starting program: /home/naba/apps/dbgtst
Breakpoint 1, main () at dbgtst.c:10
10 read_input(input);
(gdb) set var input=buf
(gdb) cont
Continuing.
Command: test
You typed: test
Program exited normally.
(gdb) q

As the previous listing shows, if I stop the program just before

read_input is called and set the variable named

input to

buf (which is a valid array of characters), the rest of the program runs fine.

After trying in

gdb a fix that works, you can make the necessary changes to the source files and can make the fix permanent.


/ 341