首页 > 其他分享 >GDB

GDB

时间:2024-03-20 22:44:36浏览次数:22  
标签:core 程序 gdb HelloGdb GDB 调试

GDB

GDB 能够允许查看程序执行时的内部情况,或者在程序出现崩溃的瞬间正在做什么。

GDB 可以做四种主要的功能来帮助捕获错误:

  • 启动程序,指定可能影响其行为的变量或条件
  • 使程序在指定条件或者位置停止
  • 检查程序停止时发生了什么
  • 更改程序中的内容,以便可以尝试更正当前已了解到的错误,然后继续调试程序,了解下一个错误

GDB支持的语言链接

使用 GDB 的条件

想要使用 GDB 进行调试程序,需要在编译程序时加入 -g 选项,让编译的程序中保留 调试符号信息。此外,最好在编译时同时加上 -O0-O能够设置编译器对我们程序的优化选项,分别由 0 - 4 五个级别,而 -O0 为让编译器不对程序做出优化,已能够准确定位错误点。


启动 GDB

启动 GDB 调试程序主要有以下三种方式

  1. gdb filename: 直接调试目标程序
  2. gdb attach pid: 附加进程
  3. gdb filename corename: 调试 core 文件

退出GDB
退出 GDB 调试命令行界面比较简单,输入 quit 或简写 q ,以及 ctrl + d 均可退出。

接下来依次介绍这三种启动方式。现在先准备一个测试程序:

// HelloGdb.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("Hello GDB\n");

    int i = 0;
    while(1) {
        i++;

        if (i == 100) {
            i = 0;
        }
    }

    return 0;
}

然后进行编译:

gcc -g -O0 HelloGdb.c -o HelloGdb

直接启动

gdb ./HelloGdb

附加进程

如果是在进程已经存在情况下,我们想在不重启该程序的情况下对其进行调试,则可以使用附加进程调试的方式。

获取进程PID

使用ps命令获取 HelloGdb 进程的 PID:

ps -ef | grep HelloGdb

# 输出如下
# h47         5130    3602  0 15:35 pts/0    00:00:00 ./HelloGdb
# h47         5249    5146  0 15:36 pts/1    00:00:00 grep --color=auto HelloGdb

可见,HelloGdb 的进程 PID 为 5130

gdb附加进程PID

接下来使用 GDB 附加进程,需要以 root 权限执行。

sudo gdb attach 5130

当用 sudo gdb attach PID 成功附加上目标进程后,调试器会将程序暂停下来,此时可以进行查看代码、添加断点等 GDB 操作,然后可以使用 continue 让程序继续运行。

当调试完程序想结束此次调试时,想单独退出GDB而不对当前进程产生影响,让其可以继续运行,可以在 GDB 命令行输入 detach 命令实现,这样进程就可以继续运行了。再使用 quit 退出GDB即可。

调试 core 文件

在实际工作中,常能见到程序在跑机测试中,运行一段时间后会偶现崩溃,这种崩溃难以及时追踪,于是可以调试 core 文件的方式追踪问题。

只要程序在崩溃时就会有 core 文件产生,就可以使用这个 core 文件来定位原因。

可以使用 ulimit -c 命令查看是否开启程序崩溃产生 core 文件的机制(Linux 系统默认不开启)。

ulimit -c

# 返回
# 0

执行以下步骤修改设置可生成 corefile :

# 打开 /etc/profile 文件
sudo vi /etc/profile

# 在该文件末新增下面语句,并保存退出
ulimit -c unlimited

# 使修改立即生效
source /etc/profile

# 查看修改是否生效
ulimit -c

执行以下步骤,指定生成 corefile 的路径:

  1. /etc/sysctl.conf 写入 corefile 文件生成的目录, 并创建该目录。
kernel.core_pattern=/home/h47/core_dump/core-%e-%p-%t

mkdir /home/h47/core_dump

/home/h47/core_dump/ 对应指定存放的路径
core-%e-%p-%t 对应文件格式

格式控制参数表如下:

参数 说明
%% 相当于%
%p pid 值
%u uid 值
%g gid 值
%s 导致dump的信号的数字
%t dump的时间
%e 执行文件名称
%h hostname
  1. 执行生效
sudo sysctl -p /etc/sysctl.conf
  1. 查看是否生效
cat /proc/sys/kernel/core_pattern

不指定生成路径,则会在执行文件的同级目录下生成 corefile

修改测试范例
我们还需要修改一下测试范例,让其在运行时崩溃:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    printf("Hello GDB\n");

    int i = 0;
    while(1) {
        i++;

        // 让程序5s后崩溃
        if (i == 5) {
            printf("G\n");
            *(char *)0 = 0;
            i = 0;
        }
        sleep(1);
    }

    return 0;
}

执行程序崩溃后,能在设置的路径看到生成了 corefile,接下来使用以下命令进行调试:

gdb ./HelloGdb /home/h47/core_dump/core-HelloGdb-2851-1710927155

./HelloGdb 是可执行文件名称
/home/h47/core_dump/xxxxx 是刚刚生成的 corefile 的绝对路径

接着输入 bt 查看堆栈。


常用命令

命令名称 命令缩写 命令说明
run r 运行程序
continue c 让暂停的程序继续运行
next n 单步跳过,运行到下一行
step s 但不进入,进入调用的函数内部
until u 运行到指定行
finish fi 单步跳出,跳出当前函数,到上一层函数调用处
return 跳出当前函数并返回指定值,到上一层函数调用处
jump j 将当前程序执行流跳转到指定行或地址
print p 打印变量或寄存器值
backtrace bt 查看当前线程的调用堆栈
frame f 切换到当前调用线程的指定堆栈,具体堆栈通过堆栈序号指定
thread thread 切换到指定线程
break b 添加断点
tbreak tb 添加临时断点
delete del 删除断点
enable 启用某个断点
disable 禁用某个断点
watch 监视某一个变量或内存地址的值是否发生变化
list l 显示源码
info 查看断点/线程等信息
ptype 查看变量类型
disassemble dis 查看汇编代码
set args 设置程序启动命令行参数
show args 查看设置的命令行参数

标签:core,程序,gdb,HelloGdb,GDB,调试
From: https://www.cnblogs.com/-h47/p/18086298

相关文章

  • 使用Python-psycopg访问postgres、openGauss、MogDB
    摘要Psycopg是一种用于执行SQL语句的PythonAPI,可以为PostgreSQL、GaussDB数据库提供统一访问接口,应用程序可基于它进行数据操作。Psycopg2是对libpq的封装,主要使用C语言实现,既高效又安全。它具有客户端游标和服务器端游标、异步通信和通知、支持“COPYTO/COPYFROM”......
  • vim,gcc,gdb与Makefile的使用
    一、Linux编辑器-vim使用1.vim的基本概念vim的三种模式(其实有好多模式,目前掌握这3种即可),分别是命令模式(commandmode)、插入模式(Insertmode)和底行模式(lastlinemode),各模式的功能区分如下(1)正常/普通/命令模式(Normalmode)控制屏幕光标的移动,字符、字或行的删除,移动复制......
  • 使用 gdb 查看 coredump 文件的 backtrace
    问题背景程序退出过程中卡死,但是一旦开启log就无法复现问题。于是考虑获取程序卡死时的coredump文件,分析其调用栈。一种方法是在程序卡死时,用kill命令向其发送一个信号,使程序产生coredump文件。前提Target上可以产生core文件(如/tmp/<executable-name>-<pid>.core),......
  • gdb调试工具使用教程
    编译的时候必须带-g才会有调试信息常用的命令l=list主函数源码列出多行的办法,默认是十行,两个参数用逗号隔开,前面是开始,后面是终止行b=breakpoint设置断点后面跟数字行数,b6,代表第六行设置断点,infob可以看到所有断点的设置情况,可以用delete删除断点r=run全......
  • MogDB-openGauss中的聚集与分组操作
    MogDB/opengauss中的聚集与分组操作COUNT:对结果集中的元组数量进行计数,如果是COUNT(*),那么会统计所有元组(包括NULL值)的数量,如果是COUNT(colname),那么会忽略NULL值,只统计非NULL值的数量。SUM:对参数中属性的所有值求和。AVG:对参数中属性的而所有值取平均值,要求列的类型......
  • MogDB-opengauss中的连接操作-1
    MogDB/opengauss中的连接操作-1如果FROM关键字后由超过2个及以上(含2个)的表参与连接操作,则该查询可以成为连接查询,也可以叫作多表查询。连接查询是SQL种最基本的操作,它的本质是多个表之间做笛卡尔积,借由这个思想又衍生出自然连接、θ连接等。以下以t1、t2、t3几个基......
  • MogDB-openGauss事务处理语句
    MogDB/openGauss事务处理语句事务是由一组SQL语句序列构成的原子操作集合,它具有原子性、一致性、隔离性和持久性的特点。用户在开始执行一个SQL语句时,实际上就已经开始了一个隐式的事务,而SQL语句执行结束,隐式的事务也会根据SQL语句的执行成功与否分別进行提交(Commit)......
  • MogDB-openGauss视图与物化视图
    MogDB/openGauss视图与物化视图一个数据库通常分成外模式、模式和内模式三种模式:外模式:也叫用户模式,是用户所能访问的一组数据视图,和某一应用的逻辑结构有关,是从模式中导出的一个子集,针对某一具体应用控制访问的可见性。模式:数据库内所包含的逻辑结构,包括基本表的定义等。内......
  • MogDB-openGauss中的集合操作
    MogDB/opengauss中的集合操作UNION:并操作,将UNION关键字两段的结果集做并集操作。EXCEPT:差操作,从左侧的结果集中排除掉右侧的结果集。INTERSECT:交集,对两个结果集做取交集操作。对表t1、t2做UNION操作,具体语句如下:MogDB=#SELECT*FROMt1UNIONSELECT*FROMt2;c1......
  • MogDB-opengauss存储过程的修改
    MogDB/openGauss存储过程的修改SQL中没有提供显式的存储过程修改命令,通常需要通过REPLACE关键字来指定使用当前的存储过程替代之前的同名存储过程。将前文定义的存储过程替换为按照地区分组的数量统计,具体语句如下:MogDB=#CREATEORREPLACEPROCEDUREwarehouse_count()L......