目录linux
首先使用gdb的前提是编译的时候加上-g参数。例若有一下代码c++
/* bugging.c */ #include <stdio.h> int foo(int n) { int sum; int i; for (i=0; i<=n; i++) { sum = sum+i; } return sum; } int main(int argc, char** argv) { int result = 0; int N = 100; result = foo(N); printf("1+2+3+...+%d= %d\n", N, result); return 0; }
首先编译文件,若是gdb没安装的自行sudo安装下shell
g++ bugging.c -g
1,敲击run
执行程序,结果以下,退出为quitbash
(gdb) run Starting program: /home/cwl/Desktop/code/gdb/gdbtest/a.out 1+2+3+...+100= 26895 [Inferior 1 (process 6322) exited normally]
其余相关命令app
命令 | 简写形式 | 说明 |
---|---|---|
list | l | 查看源码 |
backtrace | bt、where | 打印函数栈信息 |
next | n | 执行下一行 |
step | s | 一次执行一行,遇到函数会进入 |
finish | 运行到函数结束 | |
continue | c | 继续运行 |
break | b | 设置断点 |
info breakpoints | 显示断点信息 | |
delete | d | 删除断点 |
p | 打印表达式的值 | |
run | r | 启动程序 |
until | u | 执行到指定行 |
info | i | 显示信息 |
help | h | 帮助信息 |
在 gdb 命令行界面,输入 help command
能够查看命令的用法,command 是你想要查询的命令。函数
在 gdb 命令行界面能够执行外部的 Shell 命令:!shell 命令
ui
list 行号 list 文件名:行号 list 函数名
break 行号,断点设置在该行开始处,注意:该行代码未被执行 break 文件名 : 行号,适用于有多个源文件的状况。 break 函数名,断点设置在该函数的开始处,断点所在行未被执行: break 文件名 : 函数名,适用于有多个源文件的状况。
info breakpoints 命令用于显示当前断点信息。 其中 --- Num 列表明断点编号,该编号能够做为 delete/enable/disable 等控制断点命令的参数 Type 列表明断点类型,通常为 breakpoint Disp 列表明断点被命中后,该断点保留(keep)、删除(del)仍是关闭(dis) Enb 列表明该断点是 enable(y) 仍是 disable(n) Address 列表明该断点处虚拟内存的地址 What 列表明该断点在源文件中的信息
delete Num,删除指定断点,断点编号可经过 info breakpoints 得到: delete,不带任何参数,默认删除全部断点:
disable 命令和 enable 命令分别用于关闭和启用断点:spa
disable 命令用于关闭断点,有些断点可能暂时不须要但又不想删除,即可以 disable 该断点。命令行
enable 命令用于启用断点。调试
disable Num,关闭指定断点,断点编号可经过 info breakpoints 得到: disable,不带任何参数,默认关闭全部断点。 enable Num,启用指定断点,断点编号可经过 info breakpoints 得到。 enable,不带任何参数,默认启用全部断点。
disable 和 enable 命令影响的是 info breakpoints 的 Enb 列,表示该断点是启用仍是关闭
调试的过程当中须要观察变量或者表达式的值,因此先介绍两个基本的显示变量值的命令:
info locals
打印当前断点处所在函数的全部局部变量的值,不包括函数参数。
print 变量或表达式
打印表达式的值,可显示当前函数的变量的值、全局变量的值等
print/FMT
能够控制打印的格式,常见的有x(十六进制)、t(二进制)、c(显示为字符)等。
run 命令用于启动待调试程序,并运行到断点处停下。
run
不带任何参数,启动待调试程序,不传递参数。
run 参数
有些程序须要跟参数,直接带上参数列表便可,会传递给 main 函数的 argc、argv 变量。
next, step, finish, continue, until 用于控制整个调试过程当中,程序执行的流程。
next
next 单步执行,函数调用当作一条指令,不会进入被调用函数内部
next N,表示单步执行N次
step
step 单步执行,会进入到函数调用内部
step N,表示单步执行N次
finish
执行程序到当前函数结束
continue
执行程序到下个断点
until
until N,执行程序到源代码的某一行
gdb bugging > (gdb) break foo > (gdb) info breakpoints run info proc mappings #查看待调试进程的内存分布状况
下面[STACK]就是进程栈空间了
process 12217 Mapped address spaces: Start Addr End Addr Size Offset objfile 0x555555554000 0x555555555000 0x1000 0x0 /home/cwl/Desktop/code/gdb/gdbtest/a.out 0x555555754000 0x555555755000 0x1000 0x0 /home/cwl/Desktop/code/gdb/gdbtest/a.out 0x555555755000 0x555555756000 0x1000 0x1000 /home/cwl/Desktop/code/gdb/gdbtest/a.out 0x555555756000 0x555555777000 0x21000 0x0 [heap] 0x7ffff70f2000 0x7ffff72a3000 0x1b1000 0x0 /lib/x86_64-linux-gnu/libc-2.27.so 0x7ffff72a3000 0x7ffff74a2000 0x1ff000 0x1b1000 /lib/x86_64-linux-gnu/libc-2.27.so 0x7ffff74a2000 0x7ffff74a6000 0x4000 0x1b0000 /lib/x86_64-linux-gnu/libc-2.27.so 0x7ffff74a6000 0x7ffff74a8000 0x2000 0x1b4000 /lib/x86_64-linux-gnu/libc-2.27.so 0x7ffff74a8000 0x7ffff74ac000 0x4000 0x0 0x7ffff74ac000 0x7ffff74c3000 0x17000 0x0 /lib/x86_64-linux-gnu/libgcc_s.so.1 0x7ffff74c3000 0x7ffff76c2000 0x1ff000 0x17000 /lib/x86_64-linux-gnu/libgcc_s.so.1 0x7ffff76c2000 0x7ffff76c3000 0x1000 0x16000 /lib/x86_64-linux-gnu/libgcc_s.so.1 0x7ffff76c3000 0x7ffff76c4000 0x1000 0x17000 /lib/x86_64-linux-gnu/libgcc_s.so.1 0x7ffff76c4000 0x7ffff7856000 0x192000 0x0 /lib/x86_64-linux-gnu/libm-2.27.so 0x7ffff7856000 0x7ffff7a55000 0x1ff000 0x192000 /lib/x86_64-linux-gnu/libm-2.27.so 0x7ffff7a55000 0x7ffff7a56000 0x1000 0x191000 /lib/x86_64-linux-gnu/libm-2.27.so 0x7ffff7a56000 0x7ffff7a57000 0x1000 0x192000 /lib/x86_64-linux-gnu/libm-2.27.so 0x7ffff7a57000 0x7ffff7bc9000 0x172000 0x0 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25 0x7ffff7bc9000 0x7ffff7dc9000 0x200000 0x172000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25 0x7ffff7dc9000 0x7ffff7dd3000 0xa000 0x172000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25 0x7ffff7dd3000 0x7ffff7dd5000 0x2000 0x17c000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25 ---Type <return> to continue, or q <return> to quit--- 0x7ffff7dd5000 0x7ffff7dd8000 0x3000 0x0 0x7ffff7dd8000 0x7ffff7dfd000 0x25000 0x0 /lib/x86_64-linux-gnu/ld-2.27.so 0x7ffff7fce000 0x7ffff7fd4000 0x6000 0x0 0x7ffff7ff7000 0x7ffff7ffa000 0x3000 0x0 [vvar] 0x7ffff7ffa000 0x7ffff7ffc000 0x2000 0x0 [vdso] 0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x24000 /lib/x86_64-linux-gnu/ld-2.27.so 0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x25000 /lib/x86_64-linux-gnu/ld-2.27.so 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0 0x7ffffffdc000 0x7ffffffff000 0x23000 0x0 [stack] 0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
backtrace 查看函数调用栈的状况
backtrace、where、info stack
这三个命令均可以查看函数的调用状况
backtrace full、where full、info stack full
这三个命令查看函数调用状况的同时,打印全部局部变量的值
栈帧(stack frame)
#1 是 main 函数用到的栈空间,这一部分能够称之为 main 函数的 stack frame
#0 是 foo 函数用到的栈空间,一样可称之为 foo 函数的 stack frame,0 表明当前执行停在 foo 函数内
能够获得函数调用关系为,main 调用 foo
info frame Num 查看某个函数栈帧的详细信息
(gdb) info frame 0 # <=============== commond ================== Stack frame at 0x7fffffffcbd0: rip = 0x555555554680 in foo (bugging.c:13); saved rip = 0x5555555546b8 called by frame at 0x7fffffffcc00 source language c++. Arglist at 0x7fffffffcbc0, args: n=100 Locals at 0x7fffffffcbc0, Previous frame's sp is 0x7fffffffcbd0 Saved registers: rbp at 0x7fffffffcbc0, rip at 0x7fffffffcbc8 (gdb) info frame 1 # <=============== commond ================== Stack frame at 0x7fffffffcc00: rip = 0x5555555546b8 in main (bugging.c:24); saved rip = 0x7ffff7113a87 caller of frame at 0x7fffffffcbd0 source language c++. Arglist at 0x7fffffffcbf0, args: argc=1, argv=0x7fffffffccd8 Locals at 0x7fffffffcbf0, Previous frame's sp is 0x7fffffffcc00 Saved registers: rbp at 0x7fffffffcbf0, rip at 0x7fffffffcbf8