Linux高级--1.4 gdb调试

1. GDB 调试概述及原理

GDB(GNU Debugger)是 GNU 项目开发的一款强大的调试工具,支持 C、C++、Fortran 等多种编程语言。它允许开发者控制程序的执行,查看变量的值,调试崩溃的程序,并提供多种用于定位和分析程序问题的功能。

GDB 的基本工作原理:

GDB 主要通过以下几种方式与程序交互:

  • 断点:在指定位置暂停程序的执行,便于开发者检查程序的状态。
  • 步进执行:逐步执行程序,检查代码的每一步执行情况。
  • 堆栈跟踪:查看程序的调用栈信息,帮助定位函数调用链的问题。
  • 动态库调试:调试时可以加载和调试共享库,查看程序依赖的动态库的状态。

GDB 由 GNU 项目开发,开源并可以从 GDB 官网GitHub 下载源代码。

GDB 原版英文文档:

GDB 的官方文档提供了详细的指导,可以从 GDB Manual 查阅。


2. GDB 环境配置及核心转储文件调试

2.1 启用核心转储文件(Core Dump)

核心转储文件是程序崩溃时生成的文件,包含了程序运行的内存信息,能帮助开发者调试和定位崩溃原因。

  1. 查看核心文件大小限制

    ulimit -c
    

    如果返回 0,表示核心文件生成被禁用。

  2. 启用核心转储

    ulimit -c unlimited
    
  3. 配置核心文件存储路径及命名: 在 /etc/sysctl.conf 中配置 core_pattern,改变核心文件的存储路径和命名规则:

    kernel.core_pattern = /path/to/core/%e.%p.core
    
    • %e 表示程序名,%p 表示进程号,使用该配置会将核心文件存储到指定路径。
  4. 使配置生效

    sysctl -p
    

2.2 调试核心转储文件:

假设已启用核心转储,生成了核心文件 core,可以通过以下命令进行调试:

gdb ./your_program core
  • 查看堆栈信息

    (gdb) backtrace
    
  • 查看变量信息

    (gdb) print x
    

2.3 核心转储文件调试快捷方式:

  • 查看堆栈:直接使用 bt 命令查看堆栈:
    (gdb) bt
    

3. GDB 断点管理

3.1 设置断点:

  1. 在函数入口设置断点

    (gdb) break main
    

    这将在 main 函数入口设置一个断点。

  2. 在指定代码行设置断点

    (gdb) break 20
    

    在源代码第 20 行设置断点。

  3. 设置条件断点: 只有在满足特定条件时才触发断点:

    (gdb) break 20 if x == 5
    
  4. 删除断点

    (gdb) delete 1
    
  5. 列出断点

    (gdb) info breakpoints
    

4. GDB 查看运行时信息

在调试过程中,查看程序的运行时信息至关重要。GDB 提供了多种命令来查看变量的值、内存内容、寄存器状态等信息。

4.1 查看变量:

  • 查看变量值

    (gdb) print x
    
  • 查看复杂表达式值

    (gdb) print x + y
    
  • 查看数组内容

    (gdb) print array[0]@10
    

4.2 查看内存和寄存器:

  • 查看内存内容

    (gdb) x/10x 0x7fffffff
    

    该命令显示从地址 0x7fffffff 开始的 10 个内存单元,每个单元以十六进制格式显示。

  • 查看寄存器值

    (gdb) info registers
    

4.3 堆栈信息:

  • 查看调用堆栈
    (gdb) backtrace
    

5. GDB 调试控制流

控制流调试功能可以让开发者精确控制程序的执行,逐步分析程序的行为。

5.1 常见控制流命令:

  1. 继续执行程序

    (gdb) continue
    
  2. 单步执行(进入函数)

    (gdb) step
    
  3. 单步执行(跳过函数)

    (gdb) next
    
  4. 跳出当前函数

    (gdb) finish
    
  5. 跳转到指定代码位置

    (gdb) jump 50
    
  6. 设置函数返回值

    (gdb) return 42
    

6. GDB 多线程调试

在调试多线程程序时,GDB 提供了强大的多线程调试功能,允许开发者分别调试每个线程。

6.1 查看线程信息:

  1. 查看所有线程

    (gdb) info threads
    
  2. 切换到指定线程

    (gdb) thread 2
    
  3. 查看当前线程堆栈

    (gdb) backtrace
    
  4. 查看当前线程的局部变量

    (gdb) print x
    

7. GDB 调试共享库

在调试程序时,可能需要加载并调试动态链接库(共享库)。GDB 提供了命令来管理动态库。

7.1 设置共享库搜索路径:

如果程序依赖于某些共享库,GDB 允许开发者设置共享库的搜索路径。通过 set solib-search-path 命令指定共享库路径:

(gdb) set solib-search-path /path/to/your/libs

7.2 查看已加载的共享库:

使用 info sharedlibrary 命令查看当前程序加载的共享库:

(gdb) info sharedlibrary

7.3 加载自定义共享库:

如果需要调试自定义的共享库,可以使用 sharedlibrary 命令手动加载:

(gdb) sharedlibrary libmylibrary.so

8. GDB 调试 C、C++ 程序的 Makefile 和 CMake 配置

为了在 GDB 中进行调试,程序必须包含调试信息。我们可以通过修改编译选项来启用调试信息。

8.1 在 Makefile 中启用调试信息:

在 Makefile 中添加 -g 编译选项,编译器会生成调试信息:

CFLAGS += -g

8.2 在 CMake 中启用调试信息:

CMakeLists.txt 文件中设置调试模式:

set(CMAKE_BUILD_TYPE Debug)

这将生成包含调试信息的程序。


9. GDB 常用操作命令

GDB 提供了一些常见的操作命令,帮助开发者更高效地进行调试。

9.1 常用命令:

  • 退出 GDB

    (gdb) exit
    
  • 查看帮助

    (gdb) help
    
  • 查看指定命令的帮助

    (gdb) help break
    
  • 显示程序源代码

    (gdb) list 20
    
  • 显示当前执行行

    (gdb) info line
    
  • 打印表达式的值

    (gdb) print expression
    
  • 修改变量的值

    (gdb) set var x = 10
    

10. GDB 调试示例

假设有以下简单的 C 代码:

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main() {
    int x = 5;
    int y = 10;
    int result = add(x, y);
    printf("Result: %d\n", result);
    return 0;
}

10.1 编译代码:

使用 -g 选项生成调试信息:

gcc -g -o test_program test_program.c

10.2 启动 GDB 调试:

启动 GDB,并设置断点:

gdb ./test_program
(gdb) break add
(gdb) run

10.3 调试过程:

  1. 程序在 add 函数处停下来。

  2. 使用 print 命令查看变量:

    (gdb) print a
    (gdb) print b
    
  3. 使用 continue 继续执行:

    (gdb) continue
    

https://github.com/0voice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值