GDB c++ 调试

GDB c++ 调试

    • 程序编译
      • 1. 安装gcc (CentOS):
      • 2. 编译
    • GDB debug
      • 1. 安装 gdb
      • 2. 进入调试环境
      • 3. 基本操作
      • 4. 设置断点
      • 5. 调试
      • 6. GDB TUI 图形界面
      • 7. 变量

GDB: GNU Debugger
GNU: GNU is Not Unix
UNIX/LINUX操作系统下的, 基于命令行的, 功能强大的程序调试工具.

程序编译

首先,在debug之前要对程序进行编译,可以用 gcc 进行编译。

检查是否安装 gcc:

rpm -qa | grep gcc

若没有gcc, 请先安装。

1. 安装gcc (CentOS):

yum -y install gcc gcc-c++ autoconf pcre pcre-devel make automake
yum -y install wget httpd-tools vim

root@DTSEACLI409540:/ # gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

2. 编译

由于我的代码环境是 c++ 11, 所以用以下命令可以编译:

g++ -g -std=c++11 skip_list.cpp -o skip_list

若不是 c++ 11, 则不需要参数 “-std=c++11”。

GDB debug

1. 安装 gdb

检查 GDB 是否安装:

rpm -qa | grep gdb

如果你使用的是 centos 的话, 一般是自带 GDB 的安装包的。可以直接用 yum 安装。

yum -y install <>

2. 进入调试环境

gdb <executable c++ file>

3. 基本操作

(gdb) run        //运行程序
(gdb) list <number>  //列出该行代码前后十行
(gdb) list <function>  //列出该函数前后十行
(gdb) list          //不加参数,则打印上次list的后面十行
(gdb) quit       //退出

例如:

(gdb) list 2
1       #include <iostream>
2       #include <vector>
3       #include <numeric>
4       #include <random>
5       #include <time.h>
6
7       using namespace std;
8
9       /*The structure of node in skiplist,
10      includes key, pointer and constructor.
(gdb) list main
290             }
291     }
292
293     //main function
294     int main()
295     {
296             SkipList l;
297             for (size_t i = 0; i < 50; i++)
298             {
299                     l.insert(i);
(gdb)
300             }
301
302             l.printNode();
303
304             l.insert(20);
305             l.printNode();
306
307             l.find(3);
308
309             l.deleteNode(4);

4. 设置断点

  1. 在某一行打断点:
(gdb) break <line number>  

例如:

(gdb) break 299
Breakpoint 1 at 0x40188c: file skip_list.cpp, line 299.
  1. 在某个函数打断点:
(gdb) break <function name>

例如:

(gdb) break SkipList::printNode()
Breakpoint 2 at 0x401635: file skip_list.cpp, line 264.
  1. 查看断点信息
(gdb) info breakpoints

例如:

(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040188c in main() at skip_list.cpp:299
2       breakpoint     keep y   0x0000000000401635 in SkipList::printNode() at skip_list.cpp:264
  1. 关闭断点
(gdb) disable <breakpoint num>

例如:

(gdb) disable 1
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x000000000040188c in main() at skip_list.cpp:299
2       breakpoint     keep y   0x0000000000401635 in SkipList::printNode() at skip_list.cpp:264
  1. 开启断点
(gdb) enable <breakpoint num>

例如:

(gdb) enable 1
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040188c in main() at skip_list.cpp:299
2       breakpoint     keep y   0x0000000000401635 in SkipList::printNode() at skip_list.cpp:264
  1. 删除断点
(gdb) delete <breakpoint num>

例如:

(gdb) delete 1
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000401635 in SkipList::printNode() at skip_list.cpp:264
  1. 删除所有断点
(gdb) delete 

例如:

(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.

5. 调试

(gdb) info breakpoints
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x000000000040188c in main() at skip_list.cpp:299
4       breakpoint     keep y   0x0000000000401635 in SkipList::printNode() at skip_list.cpp:264
(gdb) run
Starting program: /home/c_plus/skip_list

Breakpoint 3, main () at skip_list.cpp:299
299                     l.insert(i);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-36.el7_6.2.x86_64 libstdc++-4.8.5-36.el7_6.2.x86_64
(gdb)  debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-36.el7_6.2.x86_64 libstdc++-4.8.5-36.el7_6.2.x86_64

有报错。退出GDB,安装 debuginfos。

debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-36.el7_6.2.x86_64 libstdc++-4.8.5-36.el7_6.2.x86_64

安装需要几分钟。

调试命令:

run(简写c ): 其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
continue (简写c):继续执行,到下一个断点处(或运行结束)
next:(简写n),单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
step (简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
until+行号: 运行至某行,不仅仅用来跳出循环
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55)
quit:简记为 q ,退出gdb
where/bt :当前运行的堆栈列表;
bt backtrace 显示当前调用堆栈
up/down 改变堆栈显示的深度
set args 参数:指定运行时的参数
show args:查看设置好的参数
info program: 来查看程序的是否在运行,进程号,被暂停的原因。
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000401635 in SkipList::printNode() at skip_list.cpp:264
2       breakpoint     keep y   0x000000000040188c in main() at skip_list.cpp:299
(gdb) run
Starting program: /home/c_plus/skip_list
Breakpoint 2, main () at skip_list.cpp:299
299                     l.insert(i);
(gdb) n
key: 0, randomLevel: 4
297             for (size_t i = 0; i < 50; i++)
(gdb) n
Breakpoint 2, main () at skip_list.cpp:299
299                     l.insert(i);
(gdb) n
key: 1, randomLevel: 2
297             for (size_t i = 0; i < 50; i++)

(gdb) continue
Continuing.
key: 5, randomLevel: 1
Breakpoint 2, main () at skip_list.cpp:299
299                     l.insert(i);
(gdb) continue
Continuing.
key: 6, randomLevel: 1
Breakpoint 2, main () at skip_list.cpp:299
299                     l.insert(i);

(gdb) step
SkipList::insert (this=0x7fffffffe2f0, x=11) at skip_list.cpp:162
162             int x_level = randomLevel();
(gdb) step
SkipList::randomLevel (this=0x7fffffffe2f0) at skip_list.cpp:108
108             int random_level = 1;
(gdb) step
109             int seed = time(NULL);
(gdb) step
110             static default_random_engine e(seed);
(gdb) step
111             static uniform_int_distribution<int> u(0, 1);

当然,GDB可以用于更底层的一些信息的查看,例如查看当前调用堆栈 backtrace(bt), 查看线程信息 info threads (i t), 甚至寄存器信息 info registers (i r)

这一块具体的使用我还了解的不是很清楚,希望之后有更加深入的理解了之后再来补充。

Breakpoint 1, SkipList::printNode (this=0x7fffffffe2f0) at skip_list.cpp:264
264             for (size_t i = 0; i < maxLevel; i++)
(gdb) backtrace
#0  SkipList::printNode (this=0x7fffffffe2f0) at skip_list.cpp:264
#1  0x00000000004018b8 in main () at skip_list.cpp:302

(gdb) info threads
  Id   Target Id         Frame
* 1    process 12190 "skip_list" SkipList::printNode (this=0x7fffffffe2f0) at skip_list.cpp:264

(gdb) info registers
rax            0x7fffffffe2f0   140737488347888
rbx            0x0      0
rcx            0x0      0
rdx            0x607210 6320656
rsi            0x0      0
rdi            0x7fffffffe2f0   140737488347888
rbp            0x7fffffffe2e0   0x7fffffffe2e0
rsp            0x7fffffffe2a0   0x7fffffffe2a0
r8             0x0      0
r9             0x8      8
r10            0x3      3
r11            0x246    582
r12            0x400c30 4197424
r13            0x7fffffffe410   140737488348176
r14            0x0      0
r15            0x0      0
rip            0x401635 0x401635 <SkipList::printNode()+13>
eflags         0x206    [ PF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0

6. GDB TUI 图形界面

GDB 有一个简单的图形界面可供大家调试使用。

使用如下命令即可打开图形界面:

gdb --tui a.out

界面如图所示:
GDB c++ 调试_第1张图片
可以看到有上下两个窗口,一个窗口用来显示我们用来调试的程序,另外一个用于输入GDB命令。

调试时界面如下:
GDB c++ 调试_第2张图片
图形界面退出命令为:

Ctrl + X + A

在已经进入 GDB 环境后,还可以通过如下命令进入 TUI :

(gdb) wi

7. 变量

打印变量 print <>

(gdb) p l
$2 = {head = 0x606010, minInt = -2147483648, maxInt = 2147483647, maxLevel = 6, tail = 0x606080}

监控变量 watch <>, info watch

(gdb) watch l
Hardware watchpoint 2: l
(gdb) info watch
Num     Type           Disp Enb Address            What
2       hw watchpoint  keep y                      l

查看变量类型 whatis <>

(gdb) whatis l
type = SkipList

你可能感兴趣的:(GDB c++ 调试)