网站建设分金手指专业十九,长春做线上推广的科技公司,网页界面设计风格多样化研究,公司一定建设网站吗参考:https://blog.csdn.net/Stars_WW/article/details/88994391 gdb常用交互命令 启动gdb后#xff0c;进入到交互模式#xff0c;通过以下命令完成对程序的调试#xff1b;注意高频使用的命令一般都会有缩写#xff0c;熟练使用这些缩写命令能提高调试的效率#xff1b;…参考:https://blog.csdn.net/Stars_WW/article/details/88994391 gdb常用交互命令 启动gdb后进入到交互模式通过以下命令完成对程序的调试注意高频使用的命令一般都会有缩写熟练使用这些缩写命令能提高调试的效率 运行
run简记为 r 其作用是运行程序当遇到断点后程序会在断点处停止运行等待用户输入下一步的命令; continue 简写c 继续执行到下一个断点处或运行结束; next简写 n单步跟踪程序当遇到函数调用时也不进入此函数体此命令同 step 的主要区别是step 遇到用户自定义的函数将步进到函数中去运行而 next 则直接调用函数不会进入到函数体内; step 简写s单步调试如果有函数调用则进入函数与命令n不同n是不进入调用的函数的; until当你厌倦了在一个循环体内单步跟踪时这个命令可以运行程序直到退出循环体; until行号 运行至某行不仅仅用来跳出循环; finish 运行程序直到当前函数完成返回并打印函数返回时的堆栈地址和返回值及参数值等信息; call 函数(参数)调用程序中可见的函数并传递“参数”如call gdb_test(55) quit简记为 q 退出gdb。 设置断点
break n 简写b n:在第n行处设置断点可以带上代码路径和代码名称 b OAGUPDATE.cpp:578 b fn1 if ab条件断点设置 break funcbreak缩写为b在函数func()的入口处设置断点如break cb_button delete 断点号n删除第n个断点 disable 断点号n暂停第n个断点 enable 断点号n开启第n个断点 clear 行号n清除第n行的断点 info b info breakpoints 显示当前程序的断点设置情况 delete breakpoints清除所有断点 查看源代码
list 简记为 l 其作用就是列出程序的源代码默认每次显示10行。 list 行号将显示当前文件以“行号”为中心的前后10行代码如list 12 list 函数名将显示“函数名”所在函数的源代码如list main list 不带参数将接着上一次 list 命令的输出下边的内容。 打印表达式 5. print 表达式简记为 p 其中“表达式”可以是任何当前正在被测试程序的有效表达式比如当前正在调试C语言的程序那么“表达式”可以是任何C语言的有效表达式包括数字变量甚至是函数调用。 6. print a将显示 a 的值 7. print gdb_test(a)将以变量 a 作为参数调用 gdb_test() 函数 8. display 表达式在单步运行时将非常有用使用display命令设置一个表达式后它将在每次单步进行指令后紧接着输出被设置的表达式及值。如 display a 9. watch 表达式设置一个监视点一旦被监视的“表达式”的值改变gdb将强行终止正在被调试的程序。如 watch a 10. whatis 查询变量或函数 11. info function 查询函数 12. 扩展info locals 显示当前堆栈页的所有变量
查询运行信息
where/bt 当前运行的堆栈列表 bt backtrace 显示当前调用堆栈 up/down 改变堆栈显示的深度 set args 参数:指定运行时的参数 show args查看设置好的参数 info program 来查看程序的是否在运行进程号被暂停的原因。 分割窗口
layout用于分割窗口可以一边查看代码一边测试 layout src显示源代码窗口 layout asm显示反汇编窗口 layout regs显示源代码/反汇编和CPU寄存器窗口 layout split显示源代码和反汇编窗口 Ctrl L刷新窗口
gdb解决Segmentation fault范例 我们打算使用gdb去解决为什么下面的程序文件为segfault.c引起了段错误的问题。
#include stdio.h
#include stdlib.hint main(int argc, char **argv)
{char *buf;buf malloc(131);fgets(buf, 1024, stdin);printf(%s\n, buf);return 1;
}
第一步是使用带有调试标志debugging flags的方式编译这段代码如下
~# gcc -g segfault.c
然后运行
~# a.out
Hello World!
Segmentation fault
这并不是我们所期待的。是时候启动强大的gdb了。
~# gdb a.out
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type show copying to see the conditions.
There is absolutely no warranty for GDB. Type show warranty for details.
This GDB was configured as i686-pc-linux-gnu...
(gdb)
我们直接运行就来看看到底发生了什么
(gdb) run
Starting program: /home/dgawd/cpsc/363/a.out
test stringProgram received signal SIGSEGV, Segmentation fault.
0x4007fc13 in _IO_getline_info () from /lib/libc.so.6我们收到了来自操作系统的SIGSEGV信号。这就意味着我们试图去访问一段非法的内存让我们试试backtrace bt命令
(gdb) backtrace
#0 0x4007fc13 in _IO_getline_info () from /lib/libc.so.6
#1 0x4007fb6c in _IO_getline () from /lib/libc.so.6
#2 0x4007ef51 in fgets () from /lib/libc.so.6
#3 0x80484b2 in main (argc1, argv0xbffffaf4) at segfault.c:10
#4 0x40037f5c in __libc_start_main () from /lib/libc.so.6这里我们只关心我们自己的代码因此我们就切换到3号堆栈帧stack frame3来看看程序在哪里崩溃的
(gdb) frame 3
#3 0x80484b2 in main (argc1, argv0xbffffaf4) at segfault.c:10
10 fgets(buf, 1024, stdin)哦原来是调用fgets引起的崩溃。一般的我们都假设库函数比如fgets都可以正确地工作。因此这个问题的原因就一定是其中我们的一个参数的问题。你也许不知道‘stdin’是一个全局的变量它是被stdio 库创建的。因此我们假定这个参数是正确的。那么剩下的就只能是‘buf’了然后查看buf当前的值
(gdb) print buf
$1 0x0buf的值是0x0也就是NULL指针。这并不是我们锁期待的 —— buf应该指向第8行代码分配到的内存。因此我们需要返回到第8行并看看在哪里发生了什么。首先kill掉我们程序当前运行的调用
(gdb) kill
Kill the program being debugged? (y or n) y注意:不用使用quit直接退出gdb这样比较麻烦。直接kill掉当前的程序调用即可
然后在第8行设置一个断点
(gdb) break segfault.c:8
Breakpoint 1 at 0x8048486: file segfault.c, line 8.再次运行程序
(gdb) run
Starting program: /home/dgawd/cpsc/363/a.out Breakpoint 1, main (argc1, argv0xbffffaf4) at segfault.c:8
8 buf malloc(131);我们检查malloc调用前后buf值的变化。初始化buf以前其值应该是一个随机杂乱值garbage就像这里的
(gdb) print buf
$2 0xbffffaa8 鳃?\177\003t\001\001我们step over单步执行malloc调用然后再次检查buf的值
(gdb) next
10 fgets(buf, 1024, stdin);
(gdb) print buf
$3 0x0可见调用了malloc之后buf是NULL。如果你查看malloc的手册页man page你就会发现malloc在不能分配够所需的内存的时候就会返回NULL。因此确定是我们的malloc失败了。让我们返回到代码再次看看
7 : buf malloc(131);哦表达式131整型1左移31次原文错写为右移是429497295, 或4GB (gigabytes).很少有机器会有这样的内存——大多数只有256MB显然这篇文章有年头了都什么年代了这点内存操作系统估计启动一半就挂了。因此malloc必然会失败。此外在fgets中我们只读入1024字节。所有的额外空间都会白白浪费掉尽管我们可以分配到。这里我们将131改为1024或者19这样程序就会按照我们的期望运行了
~# a.out
Hello World!
Hello World!这样你就可以知道怎样使用gdb来调试段错误了这是非常有用的。这个例子同时也说明了一个非常重要的准则总是检查malloc的返回值