GDB快速入门(举例讲解)

# 0x00

本文参考GDB官方文档的“A Sample gdb Session”部分。

# 0x01 所使用例程

本文所使用的例程为一段由C语言实现的栈代码,代码如下:

#include <stdio.h>
#include "stdlib.h"
#define  Size 4
int top = -1, Stack[Size];

void push(void);
void show(void);
void pop(void);
void enter0(void);
void enter1(void);

int main(void) {
    printf("U r in stack.c.\n");
    int choice;
    while (1) {
        printf("\nPerform operations on the stack:");
        printf("\n1.Push the element\n2.Pop the element\n3.Show\n4.End");
        printf("\n\nEnter the choice: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                push();
                break;
            case 2:
                pop();
                break;
            case 3:
                show();
                break;
            case 4:
                exit(0);
            default:
                printf("Wrong number\n");

        }
    }
    return 0;
}
zz
void push(void) {
    int input;
    if (top >= Size - 1) {
        printf("error:overflow\n");
        return;
    }
    top += 1;
    enter0();
    scanf("%d", &input);
    Stack[top] = input;

}

void pop(void) {
    if (top == -1) {
        printf("error:no more element\n");
        return;
    }

    //Stack[top] = 0;
    top -= 1;
}

void show(void) {
    if (top == -1) {
        printf("empty!\n");
        return;
    } else {
        for (int i = 0; i <= top; ++i) {
            printf("No:%d,value:%d\n", i, Stack[i]);
        }
        printf("Done!\n");
    }
}
void enter0(void){
    /*
     * 相当于 printf("Enter the element to be added onto the stack: \n");
     * 为了演示step功能,在函数里调用函数
     */
    printf("Enter the element ");
    enter1();
}
void enter1(void){
    printf("to be added onto the stack: \n");
}

代码包含了压栈、出栈、遍历栈和退出四个功能,本文主要使用压栈的push()函数进行演示。为了演示GDB的step功能,将一句printf语句里面的内容拆分成了两个函数进行调用,两个函数分别为enter0()和enter1()。

# 0x02 编译

若要使用GDB进行debug,在使用GCC编译的时候需要加入-g参数。例如本文所使用的命令为:

gcc -g -o stacks stack.c

运行后会生成名为stacks的文件。

# 0x03 预处理程序

stacks为我们需要调试的文件,使用

gdb stacks

进入调试。输出:

 

 前面是一大段的官方信息,最后一行才是我们需要看到的,GDB已经从stacks程序中读取了信息。

# 0x04 打断点

在run程序之前,我们需要对程序打断点,使其停到我们想要debug的位置。在本文中,我们针对push()函数进行debug,所以我们可以使用命令:

break push
# 或者使用break的简写b
b push

# 或者使用push()所在的行号 41行作为参数也可以
break 41
b 41

进行打断点。其中b和break等价,push和41等价。

 # 0x05 运行程序

在设置好断点之后,使用

run

命令运行程序,程序会在断点处暂停运行。

运行程序后,我们输入选项1执行压栈子程序,由于我们之前设置了断点,GDB会在push()处暂停,如上图所示。

# 0x06  逐行调试

使用如下命令执行单步调试:

next 
# 或简写
n

由上图可以看出,每执行一次逐行调试,程序会向下执行一行(当然44-46行不满足条件的代码会被跳过)。 

# 0x07 查看变量值

0x06中,我们可以看到,top执行了+1操作,由于其初始化为-1,此时其值应该为0。我们可以使用如下命令进行变量数值的查看。

print 变量名
# 或简写
p 变量名

 由上图可以看出,此时栈顶top的值为0.

# 0x08 单步调试

0x06中,我们可以看到程序即将执行第48行代码,如果我们此时使用“next”命令,那么会执行完函数到第49行。但如果我们想查看enter0()函数内部的执行情况,我们可以使用如下命令:

step
# 或简写
s

由上图我们可以看出,我们使用了step(即s)命令,调试从48行跳转到了第80行。同样,使用step命令进入enter1()后,程序从81跳转到了84行。

# 0x09 栈帧查看

进入子程序时,可以使用如下命令查看栈帧:

breaktrace
# 或缩写
bt

在本例中,我们首先进入了main(),后来进入push()、enter0()、enter1()。按照栈LIFO的原则,栈帧应该为以上函数的倒序。执行"bt"命令验证如下:

 # 0x0A 变量值修改

例程中,我们设置了栈的数组中最多存放4个数,我们可以设置栈顶变量top值为3(从0开始编号)表示栈数组已满,在下一次执行push()的时候显示执行44行代码打印溢出报错。修改变量值可以使用如下命令:

p 变量名=设定数值

 执行命令我们可以看出,top已经被修改为3.

 # 0x0B 继续运行

使用如下命令解除程序暂停状态,继续运行,直到下一个断点。

continue
# 或简写
c

由于在0xA0中,我们已经设置top为3,再次执行push()会打印溢出错误,验证如下:

 

  # 0x0C 退出调试

使用如下命令退出调试:

quit 
# 或简写
q

 在退出过程中,程序在运行会有退出确认提示,输入y回车即可退出。

--------------------------------------------------------------EOF-------------------------------------------------------------

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值