解锁 GDB:掌握 Linux 下的程序调试

GDB 全称GNU symbolic debugger,是 Linux 下常用的程序调试器。本文先介绍 gdb 的常用命令,然后介绍了怎么通过 gdb 去分析 core 的信息解决程序崩溃的问题。

1、安装 gdb

gdb -v可以查看 gdb 是否安装,安装成功会显示版本号

没有安装可以通过yum install gdb或者sudo apt install gdb进行安装。

2、gdb 的常用命令

gdb --help 可以获取 gdb 命令帮助。

下面这几个是用的比较多的命令:

  • break 简写b 设置断点。
  • run 简写r 运行到下个断点或程序结束。
  • next 简写n 单步调试,但不会进入到函数内部执行。
  • step 简写s 单步调试,会进入到函数内部执行。
  • continue 简写c 执行到下个断点或程序结束。
  • print 简写p 打印变量或表达式的值,表达式会被执行。
  • set var 设置变量的值。

更多命令可以查阅文档:www.sourceware.org/gdb/documen...

3、gdb 如何调试程序

正常使用 gcc(或 g++)命令编译生成的可执行文件,是无法使用 gdb 进行调试的。 需要在编译程序时使用-g标志来生成调试信息。

演示

下面是一段简单的从 1 累加到 10 的 C++代码,用这段代码给大家演示一下 gdb 的使用:

C++ 复制代码
#include <iostream>
using namespace std;

int main()
{

    int sum = 0;
    for(int i = 1; i <=10; i++) {
        sum += i;
        std::cout<< "i:" << i << " sum:" << sum << std::endl;
    }

    return 0;
}

先通过-g生成带有调试信息的可执行程序。

添加断点是使用b,在第 10 行添加一个断点就输入b 10,也可以添加多个断点。

使用r开始运行程序,程序运行到断点的位置会停下来,如果没有遇到断点,程序会一直运行下去。如下运行到第 10 行加的断点会停下:

使用s或者n执行下一步,进行单步调试。

使用p可以查看变量的值。

如果想在调试过程中设置变量的值,可以使用set var,如下设置 i 的值:

4、gdb 怎么分析 core 文件

在 Linux 程序运行的过程中如果发生异常崩溃,程序会被内核强行终止,系统会把发生崩溃时的内存数据、调用堆栈情况等信息保存在 core 文件中,方便程序员进一步分析。

core 文件生成的设置默认情况下是关闭的,需要手动打开。

ulimit -a显示当前系统所有的 limit 资源信息,core file size = 0 表示 Coredump 被关闭。 ulimit -c unlimited打开 Coredump。

准备如下代码,尝试将字符串 strHello 复制到一个空指针 ptrHello 中,这会导致未定义行为和程序崩溃。

c 复制代码
#include <iostream>
#include <cstring>

using namespace std;

void test() {
        char strHello[] = {"Hello World!"};
    int length = strlen(strHello);
    std::cout << "strHello length: " << length << std::endl;

    char* ptrHello = nullptr;
    strcpy(ptrHello, strHello); // 复制字符串内容
}

int main()
{
        test();
    return 0;
}

编译时同样要携带 -g 参数,g++ -o tcore -g tcore.cpp;在 ubuntu 下要记得把 apport 关掉service apport stop。否则不会生成 core 文件。运行编译生成的可执行文件可以看到生成了 core.xxxxx 文件就代表打开 Coredump 成功了。

分析 core 文件,运行gdb 程序名 core文件名即可;我这里执行的是gdb tcore core.32103

使用backtrace 可简写bt 命令查看崩溃时的调用堆栈信息,这里可以看到指向了 12 行,表明是strcpy(ptrHello, strHello);这行导致的崩溃。

总之,GDB是一个强大的工具,可帮助我们分析和调试程序,找出问题并改进代码。熟练使用GDB可以提高代码质量和开发效率。

相关推荐
雨落倾城夏未凉16 分钟前
5.通过拷贝构造函数复制一个对象,假如对象的成员中有个指针类型的变量,如何避免拷贝出来的副本中的该成员之下行同一块内存(等价于默认拷贝构造函数有没有缺点)
c++·后端
雨落倾城夏未凉18 分钟前
4.深拷贝VS浅拷贝
c++·后端
huangyuchi.19 分钟前
【Linux系统】动静态库的制作
linux·运维·服务器·动态库·静态库·库的简单制作
jim写博客1 小时前
Linux进程概念(四)环境地址变量
linux·运维·服务器
稚辉君.MCA_P8_Java1 小时前
豆包 Java的23种设计模式
java·linux·jvm·设计模式·kubernetes
tanyongxi661 小时前
C++ 特殊类设计与单例模式解析
java·开发语言·数据结构·c++·算法·单例模式
Peter(阿斯拉)1 小时前
[Java性能优化]_[时间优化]_[字符串拼接的多种方法性能分析]
java·性能优化·stringbuilder·string·字符串拼接·stringbuffer·时间优化
fqbqrr1 小时前
2508C++,支持rdma通信的高性能rpc库
c++·rpc
Nie_Xun2 小时前
ubuntu网络共享
linux·运维·ubuntu
liulilittle2 小时前
BFS寻路算法解析与实现
开发语言·c++·算法·宽度优先·寻路算法·寻路