Linux友人帐之调试器--gdb的使用

一、debug和realease版本的区别

区别

debug是给程序员用的版本,添加了调试信息,用于解决软件或程序中出现的问题,realease是发行给客户使用的版本,并未添加调试信息,只需要给客户提供优越的产品使用环境即可,至于是否能够debug调试,这是程序员才应该关心的主要问题。

可以看到debug版本的字节大小是要大于realease版本的,这是因为其中添加了调试信息。

通过指令可以读取可执行程序的二进制构成,显示出具体的二进制软件的内部所形成的特定格式。

值得注意的是:每一个二进制程序不仅仅只是一堆二进制代码,他们内部都是有特定格式的,Linux中形成的可执行程序是elf格式。

readelf命令

readelf命令是一个可以读取ELF(Executable and Linkable Format)文件头部信息的Linux命令。ELF文件是一种可执行文件和共享库的标准格式,包含了代码段、数据段、符号表和动态链接信息等。通过readelf命令,用户可以查看这些信息,如ELF文件的类型、入口地址、节区信息、符号表、重定位信息、动态链接信息等。

常用的readelf命令选项包括:

  • -a或--all:显示所有信息,默认选项;
  • -h或--file-header:显示文件头(包括ELF文件类型、入口地址等);
  • -S或--sections:显示节区信息;
  • -s或--symbols:显示符号表信息;
  • -r或--relocs:显示重定位信息;
  • -d或--dynamic:显示动态链接信息。

下面就是debug中所添加的调试信息,而realease版本是没有这些调试信息的

二、 调试器gdb

3.1gdb介绍

gdb是GNU开源组织发布的一个用于Unix/Linux的程序调试工具。

与其它调试器一样,gdb可以在程序中设置断点、查看变量值,跟踪程序执行的过程。

利用调试器的这些功能可以方便地找出程序中存在的非语法错误。

3.2环境配置

安装

编写一个用于测试的程序test.c

cpp 复制代码
#include <stdio.h>

int get_sum(int n)
{
  int sum = 0, i;
  for (i = 1; i <= n; i++)
    sum += i;
  return sum;
}

int main()
{
  int j = 100, res;
  res = get_sum(j);
  printf("1+2+...+%d = %d\n", j, res);
  return 0;
}

编译并运行该程序

gcc -g test.c -o test

需要-g参数

./test

几点注意:

  • 默认情况下,gdb无法进行对gcc现在发布的程序进行调试,因为gcc默认生成的软件是realease版本的,没有调试信息,无法被调试器gdb调试,并且gcc是默认动态链接的,如果想静态链接还需要加static选项,所有gcc是有两种默认行为的。
  • gcc编译时添加-g选项可以使得gcc发布的程序软件为debug版本,这样就可以通过gdb对程序进行调试

3.3gdb的启动和退出

启动:

  1. gdb 程序名

gdb test

  1. gdb --quiet

(gdb)file test

退出

(gdb)quit

3.4gdb常用命令

help命令

其他命令

显示程序源代码list

list: 输出从上次调用list命令开始向后的10行程序代码

list -: 输出从上次调用list命令处向前10行代码

list n: 输出n行附近的10行代码

list 函数名: 输出函数附近的10行代码

list n1,n2: 显示第n1行到n2行的代码

搜索字符串

forward/search 字符串: 从当前位置向后查找指定的字符串所在的程序行,查找时不包括当前行,可以用list n,n将当前行设置为n

reverse-search 字符串: 从当前行向前查找第一个匹配的字符串

执行程序

在shell环境下使用gdb test,或在gdb环境下使用file test只是载入了程序,但是程序是没有运行的

运行:

(gdb)run

3.5断点的设置和管理

设置断点

1 以行数设置断点

格式: break n

功能: 当程序运行到指定行时,会暂停执行,指定行的代码不执行

例如:

(gdb)break 15

(gdb)run

2 以函数设置断点

格式: break 函数名

例如:

(gdb)break get_sum

(gdb)run

3 以条件表达式设置断点

格式: break 行号或函数名 if 条件

功能: 程序在运行过程中,满足设定条件时,程序在所设置处中断

例如:

(gdb)break 7 if i==99

含义: 当程序执行到第7行时,判断条件i==99是否成立,若成立则中断

4 以条件表达式变化设置断点

格式: watch 条件表达式

功能: 程序在运行过程中,当满足设定条件时,程序中断

注意:watch必须在程序运行的过程中设置观察点,即运行run之后,并且要保证条件表达式中的变量已经使用过。

例1

(gdb)break 13

(gdb)run

(gdb)watch sum==3

例2

(gdb)break 5

(gdb)run

(gdb)watch sum==3

查看断点

查看当前设置的断点

格式: info breakpoints(info b

例如:

(gdb)break 7

(gdb)break 15 if res==5050

(gdb)info breakpoints

管理断点

1. 使中断失效或有效

失效: disable 断点编号

有效: enable 断点编号

2. 删除断点

clear 行号: 删除此行的断点

delete 断点编号: 删除指定编号的断点, 若有一次删除多个断点,各断点编号以空格分开。

delete: 删除程序中所有的断点

3. 取消断点 d + 断点编号

查看和设置变量的值

当程序执行到中断点暂停时,往往需要查看变量或表达式的值,借此了解程序的执行状态,进而发现问题。

1 print

功能: 打印变量或表达式的值,还可以用来对某个变量进行赋值。

print 变量或表达式: 打印变量或表达式的值

print 变量=: 对变量进行赋值

例如:

(gdb)break 7

(gdb)run

(gdb)print i < n

(gdb)print i

(gdb)print sum

(gdb)print i=200

(gdb)continue

2 whatis

功能: 用于显示某个变量或表达式的数据类型

格式: whatis 变量或表达式

例如:

(gdb)break 7

(gdb)run

(gdb)whatis i

(gdb)whatis sum

(gdb)whatis sum+0.5

3 set

功能: 给变量赋值

格式: set variable 变量=

4.临时查看变量或地址的值:p + 变量或地址

控制程序的执行

当程序执行到指定的中断点时,完成相关的debug操作后,可以让程序继续运行

1 continue

程序继续运行,直到下一个断点或运行完毕(运行至下一个断点处**:c(**continue))

2 kill

结束当前程序的调试

3 next/step

功能: 一次一条执行程序代码(逐过程:n(next),逐过程:n(next)

区别: next把函数调用当做一条语句来执行;step追踪进入函数,一次一条地执行内部代码。

4.跳转到指定行:until+行号

可以利用until来跳出循环

相关推荐
企服AI产品测评局19 分钟前
2026年Agent元年!深度解析实在Agent未来路线图:从自动化工具到全能数字员工的跃迁
运维·人工智能·ai·chatgpt·自动化
Leo.yuan21 分钟前
运维视角下的数据同步工具选型指南:2026年主流方案功能对比
运维
秋漓23 分钟前
Nginx学习与应用
运维·学习·nginx
TDengine (老段)24 分钟前
TDengine 数据修复与迁移 — VGroup 调度、S3 外挂与运维操作
大数据·运维·数据库·物联网·时序数据库·iot·tdengine
m0_7373025838 分钟前
读懂OpenClaw:新一代开源自主AI智能体的革新与价值
服务器
小白学大数据41 分钟前
爬虫优化:Python 剔除无效超时代理实操
服务器·爬虫·python
utf8mb4安全女神42 分钟前
shell中的判断语法
linux·运维·服务器
iDao技术魔方1 小时前
WSL 配 GPU 用 Docker 的折腾指南(2026 年版)
运维·docker·容器
2601_950368911 小时前
稀土合金粉末采购指南:3步筛选靠谱镁钆供应商
大数据·运维·人工智能·python
mifengxing1 小时前
操作系统(五)
linux·运维·服务器·操作系统·王道考研