本节我们研究gdb更深层的用法:

数据断点:

可以根据变量的值来监视变量。

数据断点本质是硬件断点,数量有限。

watch var_name告诉gdb我们关注var_name这个变量,如果它的值被改变了,程序运行就停止。

数据断点常常配合gdb里面的内存查看命令使用。

x是检查内存数据的命令。

上图中的意思是打印从0x804a024地址开始连续4个字节的数据,呈现格式以16进制打印。x代表16进制。

上图中/a代表打印地址。

变量断点和内存查看实验:

watch.c程序如下:

 #include <stdio.h>
#include <pthread.h>
#include <unistd.h> int g_var = ; void* thread_func(void* args)
{
sleep(); g_var = ;
} int main()
{
int i = ;
pthread_t tid = ; pthread_create(&tid, NULL, thread_func, NULL); for(i=; i<; i++)
{
printf("g_var = %d\n", g_var); sleep();
}
}

先编译运行一下:

子线程中将g_var的值改为1,影响到了主线程的工作,我们认为这是一个错误的程序,进行debug调试。

开始调试:

使用watch监视g_var:

continue继续执行程序:

当g_var被改变的时候,程序停下了。图中提示g_var的值被改写了,是被thread_func函数中的第12行改写的(gdb表达的意思是程序执行到第12行时,g_var的值被改写了,意味着是第11行改写的)。

查看内存的值:

上图也验证了当前系统是小端系统。

继续执行:

本次调试,我们确定了是什么地方修改了g_var的值。

函数调用相关:

为什么要打印函数调用栈呢?举个例子,当我们看一份开源代码的时候,我们想快速弄清楚函数的调用关系,这时可以在感兴趣的函数上打上断点,当程序断在这里时,可以用backtrace查看函数调用栈。

frame N可以跳转到某一个函数的上下文当中。切换过去之后可以查看一些函数参数信息等。

info fream可以查看栈帧信息。

每一次函数调用的活动记录就存在栈上,这就是栈帧。

实验:

frame.c程序如下:

 #include <stdio.h>

 int sum(int n)
{
int ret = ; if( n > )
{
ret = n + sum(n-);
} return ret;
} int main()
{
int s = ; s = sum(); printf("sum = %d\n", s); return ;
}

先编译运行一下程序:

启动gdb:

打一个条件断点:

继续执行:

程序在sum函数的第6行停下了。

backtrace打印了函数的调用信息。

main -> sum(10) -> sum(9) .... -> sum(0)

程序在sum(0)时停了下来。

next继续执行:

函数停在return ret的时候,我们通过info args打印当前栈帧这个函数参数的值,可以看到为0。

切换函数栈帧:

我们切换到7号栈帧上。

打印信息告诉我们,目前函数调用上下文里面语句停留在ret = n  + sum(n-1);这一行。

info args打印参数信息,info locals打印局部变量的值:

将栈帧切换回0号栈帧,并打印寄存器:

当前的sp的值是0xbfffee80。

打印当前栈帧的详细信息:

我们关注Previous frame's sp is 0xbfffeeb0这个信息。

这就是上一个栈帧sp的值。

调用这个函数之前,ebp的值被保存在了0xbfffeea8地址处,eip保存在了0xbfffeeac地址处。

打印函数调用之前ebp的值:

继续验证上面的打印是否正确:

执行next,sum(0)返回,这就到了sum(1)的地方:

可以看到ebp的值和上一次的打印是一样的。esp的值也完全能对应上。

调试技巧:

whatis和ptype是动态查看符号的方法。

上图中在gdb中直接编译程序。

编译后用file载入运行。

符号查看:

从上图中可知,func是一个函数类型,具体为int(),返回值为int,没有参数。

实验:

tricks.c如下:

 #include <stdio.h>

 int g_var = ;

 struct ST
{
int i;
int j;
}; int func()
{
struct ST st[] = {};
int i = ; for(i=; i<; i++)
{
st[i].i = i;
st[i].j = i * i;
} for(i=; i<; i++)
{
printf("st[%d].i = %d\n", i, st[i].i);
printf("st[%d].j = %d\n", i, st[i].j);
}
} int main()
{
static c_var = ; func(); return ;
}

开始调试:

打印结果如下:

list是列出源文件的某一行的内容,但是相邻的几行也会打印出来。

设置显示的行数重新打印:

继续执行:

使用display使得每次执行到这个断点的时候都自动打印。

最后程序正常退出:

我们再次直接run,上次设置的东西还都存在:

undisplay可以取消之前的自动打印。

使用符号查看:

ptype是打印详细的类型定义。

查看全局的变量符号:

info functions可以得到以下信息:

小结:

调试利器GDB(下)的更多相关文章

  1. linux-c/c++调试利器gdb、ddd小试

    linux-c/c++调试利器gdb.ddd小试 原文链接: http://deepfuture.iteye.com/blog/749148 博客分类: C++/C/lisp CC++C#LinuxU ...

  2. 调试利器GDB(上)

    什么是GDB: GDB应用: 静态分析工具与动态分析工具: GDB启动方式: GDB启动之后会有一个交互式的命令行,可以输入GDB特定的命令让GDB去工作. gdb test.out意思是这一次gdb ...

  3. linux 调试利器gdb, strace, pstack, pstree, lsof

    1) 如何使用strace+pstack利器分析程序性能? http://www.cnblogs.com/bangerlee/archive/2012/04/30/2476190.html 此文有详细 ...

  4. Linux C++调试利器-gdb

    在Linux上开发后台C++程序时,没有类似Windows VisualStudio那样强大的可视化IDE.为了提高调试效率,快速定位问题,需要掌握gdb工具的一些基本用法. 添加调试符号信息  co ...

  5. gdb 调试利器

    1. gdb 调试利器 GDB是一个由GNU开源组织公布的.UNIX/LINUX操作系统下的.基于命令行的.功能强大的程序调试工具.对于一名Linux下工作的c++程序猿,gdb是不可缺少的工具: 1 ...

  6. [转] linux下的c/c++调试器gdb

    PS:1. 断点C++类函数,用b 命名空间::类名::方法名 2. 编译参数一定要加-g,才可断点调试 http://www.cnblogs.com/xd502djj/archive/2012/08 ...

  7. linux下的c/c++调试器gdb

    Reference:  http://www.cnblogs.com/xd502djj/archive/2012/08/30/2663960.html linux下的c/c++调试器gdb gdbLi ...

  8. 第09课:GDB 实用调试技巧(下)

    本节课的核心内容: 多线程下禁止线程切换 条件断点 使用 GDB 调试多进程程序 多线程下禁止线程切换 假设现在有 5 个线程,除了主线程,工作线程都是下面这样的一个函数: void thread_p ...

  9. 手机H5 web调试利器——WEINRE (WEb INspector REmote)

    手机H5 web调试利器--WEINRE (WEb INspector REmote) 调试移动端页面,优先选择使用chrome浏览器调试,如果是hybrid形式的页面,可以使用chrome提供的ch ...

随机推荐

  1. keras神经网络做简单的回归问题

    咸鱼了半个多月了,要干点正经事了. 最近在帮老师用神经网络做多变量非线性的回归问题,没有什么心得,但是也要写个博文当个日记. 该回归问题是四个输入,一个输出.自己并不清楚这几个变量有什么关系,因为是跟 ...

  2. vs2015网站发布时,设置页面合并后程序集的文件版本

    如何将web网站的页面合并成一个新的程序集发布,并设定文件版本? 这个问题我也纠结了很久,问了很多大牛,也没有找到解决方案 曾开了一贴,https://bbs.csdn.net/topics/3910 ...

  3. windows硬盘优化篇

    1.数据收集(默认的族分配为4096 bytes.最好只使用第一次的计算结果,以后再运算值会一直增加.计算软件“Cluster Size Calculator”) ------------系统为w7 ...

  4. Paper Reading: Stereo DSO

    开篇第一篇就写一个paper reading吧,用markdown+vim写东西切换中英文挺麻烦的,有些就偷懒都用英文写了. Stereo DSO: Large-Scale Direct Sparse ...

  5. 关于SQLSERVER数据库连接池

    页内导航 1.如何开启连接池? 2. 那连接池是和有什么有关呢? 3.如何使用相同的连接池访问不同的数据库? ‘关于数据库连接池大家都听说过或者用过,但真正的了解有多少呢? 数据连接池如何启用?有哪些 ...

  6. 【转载】27.SpringBoot和SpringMVC的区别

    版权声明:本博客为记录本人JAVA自学之路而开,内容大多从网上学习与整理所得,若侵权请告知! https://blog.csdn.net/u014590757/article/details/7960 ...

  7. jenkins 忘记用户名和密码

    有时候会经常遇到这种情况,长时间不用会遗忘用户名和密码 admin初始密码未修改的情况 进入\Jenkins\secrets目录,打开initialAdminPassword文件,复制密码: 访问Je ...

  8. 201671010142 java内部类

    内部类可以拥有private访问权限.protected访问权限.public访问权限及包访问权限. 局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方 ...

  9. List、Set和数组之间的转换(转载)

    本文转自 http://blog.sina.com.cn/s/blog_52fea7b60100s0hl.html 今天做项目中正好遇到该问题,就在网上查了下,这篇有些细节问题还是讲得挺好的. ★ 数 ...

  10. 三元运算和bytes数据类型笔记

    三元运算 result = 值1 if条件  else 值2 如果条件为真:result = 值1 如果条件为假:result = 值2 bytes数据类型 字符串可以编码成字节包,字节包也可以解码成 ...