【Linux系统编程】代码调试工具gdb--1 https://developer.aliyun.com/article/1424715
当设置完断点后可使用 info b 指令查看我们设置的所有断点。具体的解释如下:
//使用b n 在第n行设置断点,设置完之后可观察到断点的地址、文件的来源和设置的行数 (gdb) b 5 Breakpoint 1 at 0x4007e5: file code.cpp, line 5. (gdb) b 8 Breakpoint 2 at 0x4007f5: file code.cpp, line 8. (gdb) b 11 Breakpoint 3 at 0x40081d: file code.cpp, line 11. (gdb) info b //显示所有有关断点的信息 /*Num表示断点的编号。Type表示设置类型,这里是断点。 Enb表示断点的功能的开闭,y是yes的意思,表示断点的功能正常,n是no的意思,表示断点的功能关闭,但断点还存在。Address表示断点的地址。What表示断点在哪个函数、哪个文件、哪一行中。*/ Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007e5 in main() at code.cpp:5 2 breakpoint keep y 0x00000000004007f5 in main() at code.cpp:8 3 breakpoint keep y 0x000000000040081d in main() at code.cpp:11
delete(简写:d)是删除断点的指令。使用方法:d n 删除编号为n的断点。注意,这里的n代表编号,不是行数。这里可使用info b指令查看Num中的标号。
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007e5 in main() at code.cpp:5 2 breakpoint keep y 0x00000000004007f5 in main() at code.cpp:8 3 breakpoint keep y 0x000000000040081d in main() at code.cpp:11 (gdb) d 1 //删除编号1的断点 (gdb) info b Num Type Disp Enb Address What 2 breakpoint keep y 0x00000000004007f5 in main() at code.cpp:8 3 breakpoint keep y 0x000000000040081d in main() at code.cpp:11 (gdb) d 2 //删除编号2的断点 (gdb) info b Num Type Disp Enb Address What 3 breakpoint keep y 0x000000000040081d in main() at code.cpp:11 (gdb) d 3 //删除编号3的断点 (gdb) info b No breakpoints or watchpoints. //显示断点已删除完毕
当我们设置完断点时,默认断点的功能是打开的。当我们使用 disable n(这里的n表示断点的编号) 指令时,可将编号为n的断点功能失效,但不删除。当使用 enable n(这里的n表示断点的编号) 指令时,可将编号为n的断点功能打开,与disable功能相反。
这里要说明的是,使用disable/enable后,由于调试断点的设置已被更改,当使用 r(run) 运行程序时,系统可能会提醒是否重新生成程序运行。
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007e5 in main() at code.cpp:5 2 breakpoint keep y 0x00000000004007f5 in main() at code.cpp:8 3 breakpoint keep y 0x000000000040081d in main() at code.cpp:11 (gdb) disable 2 (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007e5 in main() at code.cpp:5 2 breakpoint keep n 0x00000000004007f5 in main() at code.cpp:8 3 breakpoint keep y 0x000000000040081d in main() at code.cpp:11 (gdb) enable 2 (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007e5 in main() at code.cpp:5 2 breakpoint keep y 0x00000000004007f5 in main() at code.cpp:8 3 breakpoint keep y 0x000000000040081d in main() at code.cpp:11
逐过程和逐语句:
逐语句是一行一行进行分析,它将会进入函数内部。逐过程是一次直接执行一个过程,它将一次直接执行完一个函数,不会进行函数内部分析。
在gdb调试中,逐过程的指令是next,简写:n。逐语句的指令是step,简写:s。当在使用一次逐过程/逐语句后,下面直接按 “回车” 键即可继续往下面运行,也可不断使用n/s往下面运行,而在此过程中,我们可使用 p [变量](print的简写) 查看变量的内容,如:p n 查看数据中n的值,p &s 查看变量s的地址。这里需注意,p指令使用无法一直显示数据,当再次进行操作时,变量的内容将会消失。display [变量] 将会永久的显示数据。undisplay n(这里的n代表编号) 将会把编号为n的显示内容删除。
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007f3 in main() at code.cpp:6 2 breakpoint keep y 0x0000000000400839 in main() at code.cpp:13 3 breakpoint keep y 0x00000000004008fd in main() at code.cpp:20 4 breakpoint keep y 0x0000000000400a15 in main() at code.cpp:30 (gdb) r ......... (gdb) n //逐过程分析 8 cout << "兔子" << endl; (gdb) //回车继续运行 兔子 main () at code.cpp:9 9 i++; ......... //使用p指令显示一次数据的内容 (gdb) p i $1 = 5 (gdb) p n $2 = 10 (gdb) p &i $3 = (int *) 0x7fffffffe4dc //可发现p指令不能永久显示 (gdb) n 8 cout << "兔子" << endl; //使用display指令永久显示数据内容 (gdb) display i 1: i = 6 //i变量编号1 (gdb) display n 2: n = 10 //n变量编号2 //逐过程继续运行还会看到数据内容 (gdb) n 兔子 9 i++; 2: n = 10 1: i = 6 //使用undisplay指令删除指定数据内容,注意,这里要输入编号 (gdb) undisplay n //输入变量,出现错误 warning: bad display number at or near 'n' (gdb) undisplay 2 //输入编号2,删除编号2变量的内容 (gdb) n 8 cout << "兔子" << endl; 1: i = 8
范围式查找:
范围式调试常用指令有以下:
continue(简写:c):从一个断点运行到下一个断点或程序结束。它通常用来范围查找。
bt:查看当前函数的堆栈信息,根据函数栈帧发现问题。
finish:运行当前所在的函数,将当前所在的一个函数运行结束后就停止。但是,它不会 将主函数一次运行完。
until n(n代表行号):直接将程序运行到第n行,若中间出现死循环,在运行中将会出现死 循环问题。
以上几个指令都是在源代码基础上进行局部分析,但在调试中,我们可能会想测试源代码中某些变量改变后的情况。通常,使用 set var [改变内容] 指令即可完成。如:set var flag=0 查看将源代码中变量flag的值变为0时的测试情况。
注意:
1,使用set var指令改变内容时,要改变的变量必须已经在内部存储过,即程序已经运行到这部分时才可改变。
2,set var改变内容只是在测试中改变,不会影响源代码的内容,在测试时可放心使用。
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004007f3 in main() at code.cpp:6 2 breakpoint keep y 0x0000000000400855 in main() at code.cpp:14 3 breakpoint keep y 0x00000000004008fd in main() at code.cpp:20 4 breakpoint keep y 0x0000000000400a15 in main() at code.cpp:30 (gdb) r //run的简写,直接运行到编号1断点的位置 ............. (gdb) c //continue的简写,从当前断点位置运行到编号2断点的位置 ............. (gdb) bt #0 main () at code.cpp:14 //主函数栈帧 (gdb) until 18 //将程序从当前位置直接运行到第18行 ............. (gdb) set var i=6 //改变变量i的值 (gdb) p i //查看i已经改变过 $1 = 6 (gdb) finish //直接运行完一个函数(方法),这里程序在主函数中,因此不能正常运行 "finish" not meaningful in the outermost frame.