使用GDB调试程序(Quick Start)

一些准备工作

最基本的,安装好 gdb 程序。

以GDB调试C++程序为例,在调试前,需要将待调试的程序编译为带有可调试信息的可执行文件。

如果是使用 g++ 命令编译程序,指定 -g 选项,例如:g++ -g main.cpp -o main

如何是使用 cmake 构建项目,则在 CMakeLists.txt 文件中,在 add_executable 命令后面添加 target_compile_options 命令,例如:

cmake_minimum_required(VERSION 3.15)
project(DEMO)
add_executable(main main.cpp)
target_compile_options(main PUBLIC -g)

生成了带有可调试信息的可执行文件后,就可以使用 gdb 对程序调试了,以如下程序为简单示例,介绍常用的gdb调试命令。

// utils.h
#ifndef UTILS_H
#define UTILS_H
#include <vector>
using namespace std;

void printArr(const vector<int>& nums, int len);

#endif
// utils.cpp
#include "utils.h"
#include <iostream>

void printArr(const vector<int> &nums, int len)
{
    for (int i = 0; i < len; ++i) {
        cout << nums[i] << " ";
    }
    cout << endl;
}
#include <vector>
#include <stdlib.h>
using namespace std;

#include "utils.h"

int main(int argc, char *argv[])
{
    int len = argc - 1;
    vector<int> nums(len);
    for (int i = 1; i < len; ++i) {
        nums[i] = atoi(argv[i]);
    }
    printArr(nums, len);
    return 0;
}

常用命令

启动gdb

gdb program ,gdb 命令后跟着可执行程序名,进入 gdb 程序命令行交互,开始对该程序进行调试;需要注意的是,这只是启动了gdb 程序,被调试的程序还没有被执行,我们在启动 gdb 程序后,需要使用一系列命令来调试程序,下面将介绍一些常用的命令;

输入 quitq 退出 gdb 程序,q 为 quit 的缩写,大多数命令都有其对应的缩写命令;
在这里插入图片描述

查看程序源代码

在 gdb 程序中,使用 listl 命令查看程序源代码。
在这里插入图片描述

输入回车表示执行上一次执行的命令,即再次输入 l 命令,向下继续查看源代码;

list 命令默认显示 10 行代码,可以使用 set listsize numberset list number 命令设置一次显示的代码行数,使用 show listsizeshow list 命令查看 使用 list 命令一次显示多少行;

使用 help command 命令可以查看该命令的描述和一些可选项等;
在这里插入图片描述

list 命令默认查看的是 main 函数所在的文件中的源代码,如上图 help list 命令显示所示,可以使用 list 命令查看指定的文件中的源代码、指定文件中函数的源代码、指定文件中指定行的上下源代码;

查看指定的文件及指定行的上下文源代码,l FILENAME:LINENUM ,例如 l utils.cpp:5
在这里插入图片描述

查看指定的文件及其特定的函数的源代码,l FILENAME:FUNCTION ,例如 l utils.cpp:printArr
在这里插入图片描述

需要注意的是,使用 list 命令查看除可执行文件的其他文件的源代码时,文件名后面需要指定行号或函数名;

使用 list - 命令,表示向前查看源代码;

设置命令行参数

若程序需要从命令行输入参数,那在调试前,就需要先设置好传入程序的命令行参数,使用命令 set args 设置传入的参数,当有多个参数时,每个参数之间用空格隔开;可以使用 show args 查看设置好的参数;
在这里插入图片描述

处理 set args 命令可以设置命令行参数,在 runstart 命令的后面也可以跟着命令行参数,表示已这些参数启动程序;例如: run 1 2 3 4 5

在gdb中运行待调试的程序

使用命令 run/rstart 运行待调试的程序;start 命令会执行到 main 函数的第一行,然后暂停住,等待输入其他的 gdb 命令,而执行 run/r 命令,若没有设置断点,程序没有bug,则程序会顺利执行完毕;

(上文中已经设置了命令行参数)
在这里插入图片描述

输入命令 continue/c ,程序会从断点处继续运行,直到遇到下一个断点或程序执行完毕;
在这里插入图片描述

设置、删除、查看断点

设置断点

break/b 命令用于设置断点,有以下几种形式:

  • 在当前文件中的指定行设置断点,例如,在当前文件的第10行设置断点,break 10
  • 在当前文件中的指定函数上设置断点,当程序的执行逻辑执行到该函数时,就会触发该断点,例如,在main函数的第一行设置断点,break main
  • 在指定文件中的指定行设置断点,例如,b utils.cpp:9
  • 在指定文件中的指定函数上设置断点,当程序的执行流进入到该函数体时,才会触发该断点,例如,b utils.cpp:printArr
  • 在上面四种形式的基础上,设置条件断点,但设置的条件为true时,断点触发,通常在断点处的某个变量设置一个指定值;形式为:b 10 if val==10 ,例如在本示例程序中,b utils.cpp:7 if i==2

查看断点信息

info/i break/b 命令用于查看设置的断点信息;
在这里插入图片描述

  • Num 表示断点编号;
  • Type breakpoint, watchpoint or catchpoint;
  • Disp(Disposition) 当断点命中时,断点是否被标记为 disabled or deleted;
  • Enb 断点是否有效;
  • Address 断点在程序中的位置,作为内存地址;
  • What 断点在文件中的信息,在哪个文件,那行,或者哪个函数中;

删除断点

delete/d 命令用于删除断点,有以下形式:

  • d number 删除指定编号的断点;
  • d num1-num2 删除编号为 num1 到 num2 的断点,这些断点必须时存在的;
  • d num1 num3 num4 删除多个指定编号的断点;
    在这里插入图片描述

使断点失效、恢复失效断点

disable/dis 命令用于使断点失效,enable 命令用于恢复失效的断点;disable 和 enable 命令和删除断点的命令的使用形式相同;
在这里插入图片描述

查看变量值

print/p expr 命令用于输出变量的值,默认会根据变量的类型匹配输出的格式;
在这里插入图片描述

使用 display 命令设置的变量或表达式,没当程序暂停时,会自动打印这些设置的变量值;undisplay、disable display、enable display 命令用于删除、失效和恢复设置的变量;使用形式和删除、失效、恢复断点类似;
在这里插入图片描述

设置变量值

set var 命令用于设置变量的值,例如,set var len=3
在这里插入图片描述

单步调试

使用 next/nstep/s 命令进行单步调试;使用 step/s 命令调试时,当遇到函数时,会进入到函数体内部,而 next/n 不会进入;
在这里插入图片描述

当单步调试进入到函数体内部时,可以使用 finish 命令跳出这个函数体,前提该函数体内部没有断点;
在这里插入图片描述

使用 until 命令可以提前退出一个循环体,前提是在这个循环体内没有有效的断点,且必须在循环体的开始位置或结束位置使用该命令;
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值