• linux—常用gdb调试命令汇总


    目录

    一.准备工作

    二.调试命令

    (一).查看代码内容(l)

     (二).开始调试(r)

    (三).查看当前调试位置(where)

    (四).断点(b、info b、d、c、disable、enable)

    1.打断点

    2.显示断点

     3.删除断点

    4.调试至下一个断点

    5.关闭断点

    ​编辑 6.打开断点

    (五).打印变量和数组(p、display、undisplay)

    1.打印某变量值

     2.常显示某变量

    3.删除常显示

     (六).逐语句、逐过程调试(s、n)

    1.逐语句调试(step)

    2.逐过程调试(next)

     (七).函数(bt、finish、until)

    1.查看当前堆栈调用

    2.直接跑完当前函数

    3.执行至指定行

    (八).反汇编(disassemble)

     (九).在gdb界面执行linux指令(shell)

    (十).退出gdb(quit)


    一.准备工作

    首先,我们需要将文件编译为debug版本。因为在linux系统下,默认生成的可执行程序是release版,但是调试需要debug版本。

    我们需要在gcc或g++命令后加上限定符-g。这样生成的程序就是debug版本的。

    方式如下:

    gcc/g++ -g test.c/test.cpp -o test

    二.调试命令

    *gdp会自动记录最近的命令,如果没有输入其他命令,可以按enter键继续执行最近命令。

    (一).查看代码内容(l)

    l  命令是用来查看代码内容的。使用方式为

    l 行号        默认生成10行,当指定行号时,会生成以指定行号为中间的共10行代码

    默认不指定行号时: 

    1. (gdb) l
    2. 1 #include
    3. 2 #include
    4. 3 #include
    5. 4 #include
    6. 5 #include
    7. 6 #include
    8. 7 using namespace std;
    9. 8 int main()
    10. 9 {
    11. 10 char arr[102] = { 0 };
    12. (gdb)

     指定行号:

    1. (gdb) l 10
    2. 5 #include
    3. 6 #include
    4. 7 using namespace std;
    5. 8 int main()
    6. 9 {
    7. 10 char arr[102] = { 0 };#会以第10行为中心
    8. 11 const char* Lop = "|/-\\";
    9. 12 memset(arr, 0, sizeof(arr));
    10. 13 int i = 0;
    11. 14 for(i = 0; i <= 100; i++)
    12. (gdb)

     (二).开始调试(r)

    r命令用来开始代码调试工作,使用方式如下:

    r        开始调试,直到程序结束或遇到断点暂停。在调试过程中,再次使用r命令会重新开始调试。

     

    (三).查看当前调试位置(where)

    where        查看此时执行位置

     

    (四).断点(b、info b、d、c、disable、enable)

    1.打断点

    b 行号        在指定行打断点

    2.显示断点

    info b        显示全部断点信息,也可以在b后加编号显示指定断点

    1. (gdb) b 10 #打断点
    2. Breakpoint 3 at 0x400ac8: file cdl.cpp, line 10.
    3. (gdb) b 15
    4. Breakpoint 4 at 0x400b23: file cdl.cpp, line 15.
    5. (gdb) info b #显示断点
    6. Num Type Disp Enb Address What
    7. 3 breakpoint keep y 0x0000000000400ac8 in main() at cdl.cpp:10
    8. 4 breakpoint keep y 0x0000000000400b23 in main() at cdl.cpp:15
    9. (gdb)

     3.删除断点

    d 断点编号        删除指定断点,不加编号则删除全部

    注意断点编号不是行号,可以使用info来查看。 

    1. (gdb) info b
    2. Num Type Disp Enb Address What
    3. 5 breakpoint keep y 0x0000000000400ac8 in main() at cdl.cpp:7
    4. 6 breakpoint keep y 0x0000000000400ac8 in main() at cdl.cpp:10
    5. 7 breakpoint keep y 0x0000000000400b23 in main() at cdl.cpp:15
    6. 8 breakpoint keep y 0x0000000000400b39 in main() at cdl.cpp:17
    7. (gdb) d 5 #删除指定断点
    8. (gdb) d #删除全部断点
    9. Delete all breakpoints? (y or n) y
    10. (gdb) info b
    11. No breakpoints or watchpoints.
    12. (gdb)

    4.调试至下一个断点

    c        从当前调试位置直接执行到下一个断点处

    1. #断点为10、17、18行
    2. Num Type Disp Enb Address What
    3. 1 breakpoint keep y 0x0000000000400ac8 in main() at cdl.cpp:10
    4. 2 breakpoint keep y 0x0000000000400b39 in main() at cdl.cpp:17
    5. 3 breakpoint keep y 0x0000000000400c04 in main() at cdl.cpp:20
    6. (gdb) r #执行到第10行暂停
    7. Breakpoint 1, main () at cdl.cpp:10
    8. 10 char arr[102] = { 0 };
    9. (gdb) c #执行到第17行暂停
    10. Continuing.
    11. Breakpoint 3, main () at cdl.cpp:17
    12. 17 cout << '[' << setw(100) << arr << ']' << '[' << i << '%' << ']' << Lop[i % 4] << '\r';
    13. (gdb)

    5.关闭断点

    disable 断点编号        关闭断点 

    注意,关闭断点并不是删除断点。只是在调试时不会在该处暂停,但是断点依旧存在。 

    使用info b即可看断点关闭与否。

     6.打开断点

    enable 变量编号        打开断点

    同样的,指令需要输入的也是断点编号

     

    (五).打印变量和数组(p、display、undisplay)

    1.打印某变量值

    p 变量        打印对应的变量值,打印地址直接加取地址符&即可

    需要注意的是,这种方法只能显示一次变量值,当继续调试时变量不再显示。

    1. (gdb) p i
    2. $5 = 4
    3. (gdb) n
    4. 14 for(i = 0; i <= 100; i++)
    5. (gdb) #变量i没有再次显示

    如果我们需要打印数组的值,输入数组名即可。

     2.常显示某变量

    如果我们需要在调试中一直显示某个变量的值,那么就需要display命令了。

    display 变量        常显示指定变量值,使用方式与p一致 

    1. (gdb) display arr
    2. 3: arr = "---------", '\000' times>
    3. (gdb) c
    4. Continuing.
    5. [--------- ][9%]/
    6. Breakpoint 1, main () at cdl.cpp:17
    7. #arr数组常显示
    8. 3: arr = "----------", '\000' times>
    9. (gdb)

    3.删除常显示

    undisplay 常显示变量编号        删除指定常显示变量 

     需要注意的是,不能直接写变量名,变量编号使用info display即可知道。

     

     (六).逐语句、逐过程调试(s、n)

    1.逐语句调试(step)

    s        逐语句调试。相当于vs中的F11

    2.逐过程调试(next)

    n        逐过程调试。相当于vs中的F10 

     

     (七).函数(bt、finish、until)

    1.查看当前堆栈调用

    bt        查看当前堆栈调用 

    主要用于调试至函数内部或者递归调用函数时。 

     我们以一个递归程序举例:

    1. #include
    2. void func(int i);
    3. void func(int i)
    4. {
    5. if(i == 0) return;
    6. printf("hello world\n");
    7. func(i - 1);
    8. }
    9. int main()
    10. 3 {
    11. 4 func(3);
    12. 5 return 0;
    13. 6 }

    当我们执行至i == 1时: 

    2.直接跑完当前函数

    finish        可以直接跑完当前函数,若函数只有一层则直接跑完函数。 

    如果是函数递归调用,当还没开始递归时,finish会执行完整个函数,自动走完全部递归过程(前提无断点)。

    当已经递归调用后,在哪一层递归finish就会返回至它的前一层。 

    我们依旧以上一个递归程序为例: 

    3.执行至指定行

    until 行号        执行至指定行

    1. 1 #include"head.h"
    2. 2 void func(int i)
    3. 3 {
    4. 4 if(i == 0) return;
    5. 5 printf("hello world\n");
    6. 6 func(i-1);
    7. 7 }
    8. (gdb) until 5
    9. func (i=3) at function.c:5
    10. 5 printf("hello world\n");
    11. 1: i = 3
    12. (gdb)

    until也可以在main函数中使用,但一般until用于小范围跳动。

     

    (八).反汇编(disassemble)

    disassemble        查看指令附近区域的反汇编

     

     

     (九).在gdb界面执行linux指令(shell)

    shell 指令        在gdb界面中执行linux指令

     

    (十).退出gdb(quit)

    (gdb) quit

    1. (gdb) quit
    2. A debugging session is active.
    3. Inferior 1 [process 10341] will be killed.
    4. Quit anyway? (y or n) y
    5. [cdl@VM-16-9-centos ~]$

     

    • “一名优秀的程序员,在穿越单行道时也会确认双向的来车情况。”——道格拉斯·林德(Doug Linder)

     如有错误,敬请斧正

  • 相关阅读:
    计算机竞赛 基于深度学习的人脸专注度检测计算系统 - opencv python cnn
    使用 nlohmann 解析 json 文件
    VMware 桥接模式下本机 PING 不通虚拟机的解决方法
    二分查找【数组】
    达梦数据库 视图 错误 [22003]: 数据溢出
    SA8155P Flat Build QFIL刷机
    个人NuGet服务搭建,BaGet保姆及部署教程
    【技术】烦死了,HTML 怎么转图片?
    统一建模语言UML(4)时序图
    『忘了再学』Shell基础 — 14、环境变量(二)
  • 原文地址:https://blog.csdn.net/weixin_61857742/article/details/126067930