Http://learn.akae.cn/media/ch10s01.html
1. Single-step execution and function Tracing
See the following program:
Example 10.1. Function debugging example
#include <stdio.h>int add_range(int low, int high){int i, sum;for (i = low; i <= high; i++)sum = sum + i;return sum;}int main(void){int result[100];result[0] = add_range(1, 10);result[1] = add_range(1, 100);printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);return 0;}
add_range
Function slavelow
Addhigh
, Inmain
In the function, first add 1 to 10, save the result, then add 1 to 100, and then save the result. The two results are printed as follows:
result[0]=55result[1]=5105
The first result is correct [20], and the second result is obviously incorrect. in elementary school, we heard about the story of Gauss's childhood. The story from 1 to 100 should be 5050. For a piece of code, the first running result is correct, but the second running is incorrect. This is a common type of error. In this case, you should not doubt the Code but the data, because the first and second run is the same piece of code. If the code is wrong, why is the first result correct? However, the data related to the first and second run may be different. Wrong data may lead to incorrect results. Before you start debugging, you should first try to see if the code can tell the cause of the error. As long as the previous chapters are well-developed, you should be able to see the cause.
Add-g
Option to generate an executable file.gdb
Source code-level debugging:
$ gcc -g main.c -o main$ gdb mainGNU gdb 6.8-debianCopyright (C) 2008 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later
-g
The option is used to add source code information to the executable file. For example, the number of machine commands in the executable file corresponds to the number of lines in the source code, however, the entire source file is not embedded into the executable file, so it must be ensured during debugging.gdb
Find the source file.gdb
Provides a shell-like command line environment.(gdb)
Is a prompt. Enterhelp
You can view the command category:
(gdb) helpList of classes of commands:aliases -- Aliases of other commandsbreakpoints -- Making program stop at certain pointsdata -- Examining datafiles -- Specifying and examining filesinternals -- Maintenance commandsobscure -- Obscure featuresrunning -- Running the programstack -- Examining the stackstatus -- Status inquiriessupport -- Support facilitiestracepoints -- Tracing of program execution without stopping the programuser-defined -- User-defined commandsType "help" followed by a class name for a list of commands in that class.Type "help all" for the list of all commands.Type "help" followed by command name for full documentation.Type "apropos word" to search for commands related to "word".Command name abbreviations are allowed if unambiguous.
You can also view the commands in a category, for examplefiles
Which commands are available under the category:
(gdb) help filesSpecifying and examining files.List of commands:add-shared-symbol-files -- Load the symbols from shared objects in the dynamic linker's link mapadd-symbol-file -- Load symbols from FILEadd-symbol-file-from-memory -- Load the symbols out of memory from a dynamically loaded object filecd -- Set working directory to DIR for debugger and program being debuggedcore-file -- Use FILE as core dump for examining memory and registersdirectory -- Add directory DIR to beginning of search path for source filesedit -- Edit specified file or functionexec-file -- Use FILE as program for getting contents of pure memoryfile -- Use FILE as program to be debuggedforward-search -- Search for regular expression (see regex(3)) from last line listedgenerate-core-file -- Save a core file with the current state of the debugged processlist -- List specified function or line...
Try nowlist
Command to list the source code from the first line:
(gdb) list 11#include <stdio.h>23int add_range(int low, int high)4{5int i, sum;6for (i = low; i <= high; i++)7sum = sum + i;8return sum;9}10
Only 10 rows are listed at a time. If you want to continue with the source code of the column from row 11th, you can enter
(gdb) list
Or press enter without losing anything,gdb
A convenient function is provided. Directly press enter at the prompt to repeat the previous command.
(GDB) (Press ENTER) 11int main (void) 12 {13int result [100]; 14 result [0] = add_range (1, 10 ); 15 result [1] = add_range (1,100); 16 printf ("result [0] = % d \ nresult [1] = % d \ n", result [0], result [1]); 17 return 0; 18}
gdb
For examplelist
The command can be writtenl
To list the source code of a function, you can also use the function name as a parameter:
(gdb) l add_range1#include <stdio.h>23int add_range(int low, int high)4{5int i, sum;6for (i = low; i <= high; i++)7sum = sum + i;8return sum;9}10
Exit nowgdb
Environment:
(gdb) quit
We will conduct an experiment to rename the source code or move it elsewhere for reuse.gdb
Debugging, so that the source code is not listed:
$ mv main.c mian.c$ gdb main...(gdb) l5main.c: No such file or directory.in main.c
Visiblegcc
Of-g
The option is not to embed the source code into the executable file, and the source file is also required during debugging. Now we have restored the source code to its original state, so we can continue debugging. Usestart
Run the following command to run the program:
$ gdb main...(gdb) startBreakpoint 1 at 0x80483ad: file main.c, line 14.Starting program: /home/akaedu/main main () at main.c:1414result[0] = add_range(1, 10);(gdb)
gdb
Stopmain
The first statement after the variable definition in the function waits for us to issue a command,gdb
This statement is the next statement to be executed. We can usenext
Command (abbreviatedn
) Control the execution of these statements one by one:
(GDB) n15result [1] = add_range (1,100); (GDB) (Press ENTER) 16 printf ("result [0] = % d \ nresult [1] = % d \ n", result [0], result [1]); (GDB) (Press enter directly) result [0] = 55 result [1] = 510517 return 0;
Usen
Command to execute two rows of value assignment statement and one line of print statement, the result is immediately printed when the print statement is executed, and then stopreturn
Before the statement. Although we fully control the execution of the program, we still cannot see any errors because the errors are notmain
In the functionadd_range
Function, now usestart
Command again.step
Command (abbreviateds
) Drillingadd_range
Function to trace and execute:
(gdb) startThe program being debugged has been started already.Start it from the beginning? (y or n) yBreakpoint 2 at 0x80483ad: file main.c, line 14.Starting program: /home/akaedu/main main () at main.c:1414result[0] = add_range(1, 10);(gdb) sadd_range (low=1, high=10) at main.c:66for (i = low; i <= high; i++)
Stopped this time.add_range
The first statement after the variable definition in the function. There are several ways to view the status in the function,backtrace
Command (abbreviatedbt
) You can view the stack frame of the function call:
(gdb) bt#0 add_range (low=1, high=10) at main.c:6#1 0x080483c1 in main () at main.c:14
The currentadd_range
The function ismain
Function call,main
The input parameter islow=1, high=10
.main
The function stack frame number is 1,add_range
Stack frame number is 0. Now you can useinfo
Command (abbreviatedi
) Viewadd_range
Value of the local variable of the function:
(gdb) i localsi = 0sum = 0
If you want to viewmain
The value of the current local variable of the function can also be used.frame
Command (abbreviatedf
) Select stack 1 and then check the local variables:
(gdb) f 1#1 0x080483c1 in main () at main.c:1414result[0] = add_range(1, 10);(gdb) i locals result = {0, 0, 0, 0, 0, 0, 134513196, 225011984, -1208685768, -1081160480, ... -1208623680}
Notesresult
Many elements in the array have disordered values. We know that uninitialized local variables have undefined values. So far, everything is normal. Uses
Orn
Take a few steps down, and then useprint
Command (abbreviatedp
) Print out the variablesum
Value:
(GDB) s7sum = sum + I; (GDB) (Press ENTER) 6For (I = low; I <= high; I ++) (GDB) (Press ENTER) 7sum = sum + I; (GDB) (Press ENTER) 6For (I = low; I <= high; I ++) (GDB) P sum $1 = 3
First cyclei
Is 1, the second cyclei
It's 2. it's 3 in total. That's right. Here$1
Indicatesgdb
Save these intermediate results, and the number after $ will automatically increase. You can use$1
,$2
,$3
. Because we knew that the result of the first call was correct, it makes no sense to follow it down. You can usefinish
Command to keep the program running until the current function returns:
(gdb) finishRun till exit from #0 add_range (low=1, high=10) at main.c:60x080483c1 in main () at main.c:1414result[0] = add_range(1, 10);Value returned is $2 = 55
The return value is 55. The value assignment operation is currently being executed.s
Command assignment, and then viewresult
Array:
(gdb) s15result[1] = add_range(1, 100);(gdb) p result$3 = {55, 0, 0, 0, 0, 0, 134513196, 225011984, -1208685768, -1081160480, ... -1208623680}
The first value 55 is indeed assignedresult
The array contains 0th elements. Uses
Command to enter the secondadd_range
Call. First, check the parameters and local variables:
(gdb) sadd_range (low=1, high=100) at main.c:66for (i = low; i <= high; i++)(gdb) bt#0 add_range (low=1, high=100) at main.c:6#1 0x080483db in main () at main.c:15(gdb) i locals i = 11sum = 55
Due to local variablesi
Andsum
Not initialized, so there are uncertain values, and because the two calls are close to each other,i
Andsum
The value of the last call is exactly the same as that of example 3.7 "verifying the allocation and release of the local variable bucket", except that I tried to make the local variablesum
The initial value for the first call is 0.i
It does not matter if the initial valuesfor
In the loopi
Assignedlow
Butsum
If the initial value is not 0, the result is incorrect. Now, we have found the cause of the error. You can exit.gdb
Modified the source code. If we don't want to waste this debugging opportunity, you cangdb
Attachsum
Change the initial value to 0 to continue running. check whether there are any other bugs after this change:
(GDB) set var sum = 0 (GDB) finishrun till exit from #0 add_range (Low = 1, high = 100) at main. c: 60x08048db in main () at main. c: 1515 result [1] = add_range (1,100); value returned is $4 = 5050 (GDB) n16printf ("result [0] = % d \ nresult [1] = % d \ n", result [0], result [1]); (GDB) (Press ENTER) result [0] = 55 result [1] = 505017 return 0;
The result is correct. To modify the value of a variableset
You can also useprint
Command, becauseprint
The command is followed by an expression, and we know that both the value assignment and function call are expressions, so you can also useprint
Command to modify the value of a variable or call a function:
(gdb) p result[2]=33$5 = 33(gdb) p printf("result[2]=%d\n", result[2])result[2]=33$6 = 13
As we have said,printf
The return value indicates the number of characters actually printed, so$6
The result is 13. Summarize the information used in this section.gdb
Command:
Table 10.1. GDB basic command 1
Command |
Description |
Backtrace (or BT) |
View function calls and parameters at all levels |
Finish |
Run until the current function returns, and then stop and wait for the command. |
Frame (or F) frame number |
Stack frame selection |
Info (or I) locals |
View the value of the local variable of the current stack frame |
List (or L) |
The source code is listed, followed by 10 lines in each column at the following position. |
List row number |
List source code starting from the first line |
List function name |
List the source code of a function |
Next (or N) |
Execute the next statement |
Print (or p) |
Print the expression value. You can use the expression to modify the value of a variable or call a function. |
Quit (or Q) |
Exitgdb Debugging environment |
Set VaR |
Modify the value of a Variable |
Start |
Start executing the program and stopmain Wait for the command before the first line of the function statement |
STEP (or S) |
Execute the next statement. If a function is called, it enters the function. |