1. 前言

编写代码过程中少不了调试。在windows下面,我们有visual studio工具。在linux下面呢,实际上除了gdb工具之外,你没有别的选择。那么,怎么用gdb进行调试呢?我们可以一步一步来试试看。

先写一个代码, 文件名01_1_gdb.c

/*
 * @Author: sanjayzhong
 * @Github: https://github.com/sanjayzzzhong
 * @Date: 2019-10-02 19:30:57
 */
#include <stdio.h>

int func(int a, int b){
    int t_a = a;
    int t_b = b;
    return t_a + t_b;
}

int main(){

    int ret = 0;
    ret = func(10, 20);
    int a = 20;

    return 0;
}

既然需要调试,那么生成的可执行文件就需要包含调试的信息,这里应该怎么做呢?

很简单,输入gcc 01_1_gdb.c -g输入命令之后,如果没有编译和链接方面的错误,你就可以看到可执行文件a.out了。

2. 调试步骤

  1. 首先, 在可执行文件a.out所在的目录打开终端,输入gdb a.out

  2. 进入到gdb调试界面, 输入list,就可以看到01_1_gdb.c原文件,也就是代码

    在这里插入图片描述

  3. 设置断点, 输入b main

    在这里插入图片描述

  4. 启动程序, 输入run

    在这里插入图片描述

    程序在main开始的地方设置了断点,所以程序在int ret = 0处断住

    注意:这里显示的语句是表示下一句要执行的

  5. 这时候,可以单步跟踪。s单步可以进入到函数,而n单步则越过函数

    在这里插入图片描述

  6. 如果希望从断点处继续运行程序,输入c

  7. 希望程序运行到函数结束,输入finish

  8. 查看断点信息, 输入info break

    在这里插入图片描述

  9. 如果希望查看堆栈信息,输入bt

    在这里插入图片描述

    ps:这里的意思是只有main函数在栈中

  10. 如果希望看到更详细的堆栈信息,比如说现在的堆栈是:

    (gdb) bt
    #0  func (a=10, b=20) at 01_1_gdb.c:9
    #1  0x0000555555554638 in main () at 01_1_gdb.c:17
    

    可以输入info frame查看栈的信息:

    (gdb) info frame
    Stack level 0, frame at 0x7fffffffd780:
     rip = 0x555555554604 in func (01_1_gdb.c:9); saved rip = 0x555555554638
     called by frame at 0x7fffffffd7a0
     source language c.
     Arglist at 0x7fffffffd770, args: a=10, b=20
     Locals at 0x7fffffffd770, Previous frame's sp is 0x7fffffffd780
     Saved registers:
      rbp at 0x7fffffffd770, rip at 0x7fffffffd778
    

    然后可以指定某一层的栈:f 0

    (gdb) f 0
    #0  func (a=10, b=20) at 01_1_gdb.c:9
    9	    int t_a = a;
    (gdb) s
    10	    int t_b = b;
    (gdb) 
    11	    return t_a + t_b;
    (gdb) f 0
    #0  func (a=10, b=20) at 01_1_gdb.c:11
    11	    return t_a + t_b;
    

    但是这样只能看到栈的信息和下一行要执行的代码,如果想要看到函数里面所有的局部变量和值,应该输入:info locals:

    (gdb) info locals
    t_a = 10
    t_b = 20
    (gdb) s
    12	}
    (gdb) info locals
    t_a = 10
    t_b = 20
    (gdb) n
    main () at 01_1_gdb.c:18
    18	    int a = 20;
    (gdb) info locals
    ret = 30
    a = 0
    

    总结:

    info frame 会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句
    info args 打印出当前函数的参数名及其值。
    info locals 打印出当前函数中所有局部变量及其值。
    info catch 打印出当前的函数中的异常处理信息

  11. 希望查看内存,输入 x/64xh + 内存地址

  12. 删除断点,则输入delete break + 断点序号

  13. 希望查看函数局部变量的数值,可以输入print + 变量名

    在这里插入图片描述

  14. 希望修改内存值,直接输入print + *地址 = 数值

  15. 希望实时打印变量的数值,可以输入display + 变量名

  16. 查看函数的汇编代码,输入 disassemble + 函数名

  17. 退出调试输入quit即可

3. 函数调用流程

顺便用一张图来说明一下以上代码在执行时的调用流程,主要是在栈上:

在这里插入图片描述

Logo

更多推荐