gdb调试器

106 阅读4分钟

概述

Linux下的gdb调试器是一款GNU组织开发并发布的UNIX/Linux下的程序调试工具。它没有图形界面,但功能强大。

gdb指令参数

命令格式作用
list <行号>|<函数名>查看指定位置的程序源代码
break 行号|函数名<条件表达式>设置断点
info break显示断点信息
run运行程序
print 表达式|变量查看程序运行时对应表达式和变量的值
next单步恢复程序运行,但不进入函数调用
step单步恢复程序运行,且进入函数调用
continue继续执行函数,直到函数结束或遇到新断点

测试gdb

测试使用的代码

#include <iostream>

  void TestFun() {
    std::cout << "in TestFun" << std::endl;
    std::cout << "out TestFun" << std::endl;
  }
  
  int main() {
    std::cout << "Hello, World!" << std::endl;
    std::cout << "begin function" << std::endl;
    int i = 0;
    i++;
    i++;
    TestFun();
    std::cout << "end function" << std::endl;
    return 0;
  }
  

编译项目

g++ main.cpp -o main -g

-g参数的作用:

  • 生成可供gdb使用的调试信息。
  • 使得core dumped文件中包含更多调试信息,便于后续分析崩溃原因

开始调试

执行gdb main, main为上一步生成的函数。

 gdb main 

GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from main...
(gdb) 

展示代码

输入list指令, list后面也可以指定数字,表示要显示的行号,输出结果会显示行号的前面和后面的一部分代码

(gdb) list
1	#include <iostream>
2	
3	void TestFun() {
4	  std::cout << "in TestFun" << std::endl;
5	  std::cout << "out TestFun" << std::endl;
6	}
7	
8	int main() {
9	  std::cout << "Hello, World!" << std::endl;
10	  std::cout << "begin function" << std::endl;

查看第10行代码

(gdb) list 10
5	  std::cout << "out TestFun" << std::endl;
6	}
7	
8	int main() {
9	  std::cout << "Hello, World!" << std::endl;
10	  std::cout << "begin function" << std::endl;
11	  TestFun();
12	  std::cout << "end function" << std::endl;
13	  return 0;
14	}

设置断点

使用break命令,后面的数字可以显示行号。

(gdb) break 9
Breakpoint 1 at 0x11d2: file main.cpp, line 9.
(gdb) break 10
Breakpoint 2 at 0x11fd: file main.cpp, line 10.

显示断点信息

(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011d2 in main() at main.cpp:9
2       breakpoint     keep y   0x00000000000011fd in main() at main.cpp:10

运行程序

执行run命令

(gdb) run
Starting program: /home/magic/CLionProjects/untitled/main 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at main.cpp:9
9	  std::cout << "Hello, World!" << std::endl;

单步执行

执行next命令,单步执行,不进入函数调用

(gdb) next
Hello, World!

Breakpoint 2, main () at main.cpp:10
10	  std::cout << "begin function" << std::endl;

执行step, 单步执行,进入函数调用

(gdb) n
begin function
11	  TestFun();
(gdb) step
TestFun () at main.cpp:4
4	  std::cout << "in TestFun" << std::endl;

打印变量的值

使用print命令打印变量的值

(gdb) print i
$1 = 2

运行到下一个断点或程序退出

使用continue命令

(gdb) continue
Continuing.
in TestFun
out TestFun
end function
[Inferior 1 (process 21453) exited normally]

退出

执行quit命令

(gdb) quit

coredump测试

测试使用的代码

#include <iostream>

void TestFun() {
  std::cout << "in TestFun" << std::endl;
  std::cout << "out TestFun" << std::endl;
}

int main() {
  std::cout << "Hello, World!" << std::endl;
  std::cout << "begin function" << std::endl;
  int i = 0;
  i++;
  i++;
  int *p = 0;
  *p = 10;  // 这里故意写了一个错误
  TestFun();
  std::cout << "end function" << std::endl;
  return 0;
}

打开系统的core dump

首先查看一下系统默认的core dump,使用ulimit -c命令,查看结果为0,表示关闭了

ulimit -c
0

将core dump设置为unlimited,表示无限制。

ulimit -c unlimited

修改core dump文件生成的路径

# 编辑sysctl的配置文件
echo "kernel.core_pattern=/var/log/%e.core.%p" >> /etc/sysctl.d/99-sysctl.conf

# 应用sysctl
sysctl -p

运行程序

[root@mini-desk ~]# ./main 
Hello, World!
begin function
Segmentation fault (core dumped)

查看coredump文件

使用方式为gdb 执行程序 coredump文件

[root@mini-desk ~]# gdb main /var/log/main.core.3237
GNU gdb (GDB) Red Hat Enterprise Linux 10.2-13.el9
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from main...
[New LWP 3237]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `./main'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000401210 in main () at main.cpp:15
15	  *p = 10;  # 这里显示出了代码出错位置
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.34-100.el9_4.3.x86_64 libgcc-11.4.1-3.el9.alma.1.x86_64 libstdc++-11--Type <RET> for more, q to quit, c to continue without paging--

参考文档