调试利器GDB(下)
本节我们研究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(下)的更多相关文章
- linux-c/c++调试利器gdb、ddd小试
linux-c/c++调试利器gdb.ddd小试 原文链接: http://deepfuture.iteye.com/blog/749148 博客分类: C++/C/lisp CC++C#LinuxU ...
- 调试利器GDB(上)
什么是GDB: GDB应用: 静态分析工具与动态分析工具: GDB启动方式: GDB启动之后会有一个交互式的命令行,可以输入GDB特定的命令让GDB去工作. gdb test.out意思是这一次gdb ...
- linux 调试利器gdb, strace, pstack, pstree, lsof
1) 如何使用strace+pstack利器分析程序性能? http://www.cnblogs.com/bangerlee/archive/2012/04/30/2476190.html 此文有详细 ...
- Linux C++调试利器-gdb
在Linux上开发后台C++程序时,没有类似Windows VisualStudio那样强大的可视化IDE.为了提高调试效率,快速定位问题,需要掌握gdb工具的一些基本用法. 添加调试符号信息 co ...
- gdb 调试利器
1. gdb 调试利器 GDB是一个由GNU开源组织公布的.UNIX/LINUX操作系统下的.基于命令行的.功能强大的程序调试工具.对于一名Linux下工作的c++程序猿,gdb是不可缺少的工具: 1 ...
- [转] linux下的c/c++调试器gdb
PS:1. 断点C++类函数,用b 命名空间::类名::方法名 2. 编译参数一定要加-g,才可断点调试 http://www.cnblogs.com/xd502djj/archive/2012/08 ...
- linux下的c/c++调试器gdb
Reference: http://www.cnblogs.com/xd502djj/archive/2012/08/30/2663960.html linux下的c/c++调试器gdb gdbLi ...
- 第09课:GDB 实用调试技巧(下)
本节课的核心内容: 多线程下禁止线程切换 条件断点 使用 GDB 调试多进程程序 多线程下禁止线程切换 假设现在有 5 个线程,除了主线程,工作线程都是下面这样的一个函数: void thread_p ...
- 手机H5 web调试利器——WEINRE (WEb INspector REmote)
手机H5 web调试利器--WEINRE (WEb INspector REmote) 调试移动端页面,优先选择使用chrome浏览器调试,如果是hybrid形式的页面,可以使用chrome提供的ch ...
随机推荐
- VSCode 启动 Vue 项目 npm install 报错
1. 报错后,查看了版本. 查看node版本:node -v 查看npm版本:npm -v 查看Augular版本:ng --version 2. 感觉 Augular CLI版本太低,使用以下方 ...
- Project中最常用的注意点
最近用Project 2013做计划,做工作量的评估,感觉确实牛逼得一塌糊涂.这几天自己试着做一些手工的计算,与Project的结果进行对比,发现学到的很多东西,网上确实很难道到,花了几天的时间研究, ...
- 生成器的认识及其思考:VAE, GAN, Flow-based Invertible Model
生成器对应于认知器的逆过程. 这一切的起源都是当初一个极具启发性的思想:Sleep-wake algorithm——人睡眠时整理记忆做梦,是一个生成的过程,即通过最终的识别结果企图恢复接收到的刺激,当 ...
- 博客编辑器Open Live Writer的安装以及配置
下载安装包 访问官网 http://openlivewriter.org/ 或者微软商店 https://www.microsoft.com/en-us/p/open-live-writer/9n ...
- Ubuntu LNMP系统搭建Zabbix监控
系统环境 操作系统类型:Ubuntu 系统环境版本:4.4.0-122-generic IP地址:192.168.152.118 第一步:选择适当的操作系统类型与各项的版本要求,我这边直接使用LNMP ...
- Pandas模块
前言: 最近公司有数据分析的任务,如果使用Python做数据分析,那么对Pandas模块的学习是必不可少的: 本篇文章基于Pandas 0.20.0版本 话不多说社会你根哥!开干! pip insta ...
- 卡方分布(Chi-Square Distribution):
定义:如果我们的随机变量是标准正态分布(详见以前博客的高斯分布),那么多个随机变量的平方和服从的分布即为卡方分布. X=Y12+Y22+⋯+Yn2 其中,Y1,Y2,⋯,Yn均为服从标准正态分布的随机 ...
- leetcode 链表相关
1.给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们 ...
- 增加 jQueryValidate的手机号验证功能
1.通过addMethod增加手机号的验证方法 (位置:和$('form').validate({}) 同级别) //增加手机号验证规则 $.validator.addMethod("isM ...
- java web中验证码生成的demo
首先创建一个CaptailCode类 package com.xiaoqiang.code; import java.awt.*; import java.awt.font.FontRenderCon ...