您的位置:

堆栈-debugging神器gdb

一、gdb是什么

GDB 是 GNU Project Debugger 的缩写,是一款强大的命令行调试工具,支持多种编程语言,如C、C++、Objective-C、Pascal等等,常用于软件开发和调试。它可以让程序在运行时停下来,检查程序的状态,以及变量的值,控制程序的运行和内存的使用。

二、堆栈的作用与调试

堆是一个保存在电脑内存(RAM)中的一块区域,程序运行时,需要时刻对堆中的内存进行分配和释放,如果分配和释放的不当,会导致内存出现一系列问题,如野指针、内存泄露等。堆栈是一种用于解决内存问题的机制。在函数调用时,每个函数都有一个堆栈帧(Stack Frame)用于保存程序状态,参数和变量。当函数调用结束时,堆栈帧就会被销毁,返回到调用该函数的帧中继续执行。在进行程序调试时,堆栈的信息对于找到问题具有很大的帮助。

三、使用gdb查看堆栈

1.设置堆栈跟踪

使用 gdb 调试程序时,可以设置堆栈跟踪,以便更好的查看和分析在程序中发生的错误。 在 gdb 命令行中使用 command 命令,加上 bt 参数,就可以打开堆栈跟踪功能。更多的堆栈选项可以使用 help backtrace 命令来查看。例如:

(gdb) command 1
>bt
>end

2.查看堆栈信息

调试程序时,常常需要查看堆栈信息以帮助判断问题。在 gdb 命令行中,使用 bt (backtrace)命令可以打印出当前进程的堆栈信息。指定参数 n 表示打印最近的 n 次调用,不指定参数则表示打印所有调用。例如:

(gdb) bt 5
#0 0x00000000004011d6 in main () at test.c:5
#1 0x00000000004011c0 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00000000004010c9 in _start ()
#3 0x0000000000000000 in ?? ()

3.查看局部变量

在 gdb 命令行中,还可以查看当前所在堆栈帧中的局部变量信息。使用命令 frame n (n 为框架的编号) 可以切换到指定堆栈帧中。使用 info locals 命令可以查看当前堆栈帧中的局部变量信息。例如:

(gdb) frame 1
#1  0x08048408 in func2 () at test.c:10
10            int n = 0;
(gdb) info locals
n = 0

4.设置断点和跟踪变量

除了上述堆栈命令,gdb 还提供了设置断点和跟踪变量的功能。使用 command 命令,以及 breakpoint 和 watchpoint 命令可以通过条件语句来定义在满足条件时停止程序执行,同时记录一些关键变量的值。例如:

(gdb) break func1 if n > 10
(gdb) watch n
(gdb) backtrace
#0 func1 (n=11) at test.c:5
#1 0x08048436 in main () at test.c:17

5.使用gdb调试堆溢出问题

堆栈问题经常是程序运行时出现的问题。在堆栈溢出的情况下,我们可以使用 gdb 通过查看堆栈信息,找出问题所在,并调试解决问题。例如:

int main () {
    char *p = malloc(8);
    strcpy(p, "123456");
    printf("%s", p);
    return 0;
}

在程序运行时,当 strcpy 拷贝超过 8 字节时,将会导致堆栈溢出问题。使用 gdb 进行调试,一步一步跟踪并查看堆栈信息,可以找到这个问题的根源。例如:

(gdb) run
Starting program: /root/test 
[New Thread 2247]
[New Thread 2248]
123456Program received signal SIGSEGV, Segmentation fault.
__strcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:294
294     ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.
(gdb) bt
#0  __strcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:294
#1  0x000000000040117b in main () at test.c:7

6、使用Core Dump 进行Debug

GDB 还支持使用 Core Dump 进行调试,Core Dump 是指在程序运行崩溃时会产生一份程序内存快照,并将其写到磁盘上。当需要对程序进行调试时,可以将 Core Dump 文件加载到 GDB 中来分析。 为了启用 Core Dump,需要先执行以下命令:

  • ulimit -c unlimited:该命令设置可以生成无限量的 Core Dump 文件
  • echo "/var/core.%p.%u.%h.%t" > /proc/sys/kernel/core_pattern
  • sysctl -w kernel.core_uses_pid=1,以 PID 来区分 Dump 文件
Core Dump 文件生成后,使用以下命令加载并分析 Core Dump 文件:

gdb  
   

   
  

四、小结

使用 gdb 查看堆栈可以有效的检测到堆栈溢出问题,同时也对程序中的其他问题解决具有帮助,gdb 是一个强大的调试工具,掌握其使用方法能够大大提高程序员的调试效率。